Jquery ajax získává data z jiné domény. Cross-domain ajax s jQuery

2. prosince , 2016

Jednou jsem napsal článek o tom, jak vytvářet vložitelné widgety v nativním javascriptu a php. A všechno by bylo v pořádku, ale jeden okamžik se v něm nedotkl. Takové widgety můžete použít na svém vlastním webu, ale zajímavější je vytvořit je pro zdroje třetích stran. Ale v tomto případě musí prohlížeč načíst potřebná data z jiné domény - jedná se o požadavky ajax mezi doménami.

Z pohledu front-endového programátora se dotazy mezi doménami neliší od běžných dotazů. Ale na backendu je rozdíl. Proč s nimi není vše tak jednoduché a jak je implementovat - přečtěte si o tom v článku.

Pokus o získání dat z jiné domény

Podívejme se na získání požadavků na jednoduchost. Řekněme, že na serveru je určitý html soubor, který potřebujeme načíst ajaxem z jiné domény .. html. Otevřete jej a ujistěte se, že je skutečně k dispozici - (otevře se na nové kartě). Toto je běžný div s textem „obsah z template.html“.

Pojďme nyní získat tento html ajax přímo z konzoly prohlížeče.

Neobtěžujme se nativním javascriptem, ale zatrhneme požadavek pomocí jQuery.get () a vytiskneme na konzolu to, co jsme obdrželi v odpovědi od serveru.

$ .. html ", funkce (odpověď) (console.log (odpověď)));

Otevřete vývojářské nástroje právě teď v prohlížeči a na kartě konzoly spusťte tento požadavek.

Uvidíte něco jako následující

Všechno je skvělé, poslali jsme žádost, obdrželi odpověď. Zdá se, že co by mohlo být jednodušší? Nyní přejděte na jakýkoli jiný web, který má povolený jQuery, a zkuste to samé. Jen ne na web https, proč se dozvíte na konci článku.

Například jsem zkontroloval žádosti na fotbalovém webu bombardir.ru. A zároveň mě zajímalo, jaké odpadky nevypadly do konzoly ani na tak známých stránkách. O tom však konverzace není.

Proveďte požadavek z jiné domény a v konzole uvidíte ne tak dobrý obrázek. Říká, že je nemožné stáhnout, neexistují žádná data a obecně smutek.

Pokud otevřete kartu Síť a najdete tam odpovídající požadavek, uvidíte, že nám server dokonce vrátil 200 OK
A neexistuje žádný obsah souboru. V čem je háček?

Co se pokazilo a jaké bude řešení

Háček je v tom, že internetové zásady neumožňují prohlížečům stahovat data z jakéhokoli zdroje. Kromě případů, kdy se tyto zdroje samy zajímají o distribuci konkrétních dat.
Náš případ je právě to. Chcete-li dát oprávnění k použití souboru html odkudkoli, musíte při žádosti o tento soubor odeslat hlavičku Access-Control-Allow-Origin http: *

Nyní je otázkou, jak to udělat. Pokud vy (nebo administrátoři) máte přístup k nginx, je jedním ze způsobů, jak nakonfigurovat předávání této hlavičky pomocí webového serveru. Přejdete na administrátory s požadavkem nebo vygooglíte potřebné konfigurace pro váš webový server.

Pokud tento přístup není k dispozici, jako například u téměř jakéhokoli poskytovatele hostingu za levný tarif, musíte se dostat ven sami. Zde přichází php. Cílem je vložit náš html-ku do souboru php, který vyvolá záhlaví a poskytne požadovaný obsah.

Dopadne to takto, vytvořte soubor template.php a do prvního řádku napište příkaz php

Header ("Access-Control-Allow-Origin: *");

Obsah z template.php

To znamená, že obsah template.php bude vypadat takto, nezapomeňte na otázky a závorky php

Soubor na webdevkin je vytvořen a je (otevře se na nové kartě). Zkusme to nyní požádat z jiné domény a uvidíme, co se stane

$ .. php ", funkce (odpověď) (console.log (odpověď)));

Jak vidíte, vše funguje dobře - soubor je nahrán!

Podívejme se na kartu Síť.
Vezměte prosím na vědomí, že záhlaví Access-Control-Allow-Origin, které nás zajímá, se objevilo v bloku Záhlaví odpovědí: *

Celkově článek skončil. Zbývá shromáždit myšlenky ve skupině a přidat další informace.

Shrňte a shrňte

  • 1. Nemůžete jen požádat ajax o jakýkoli zdroj z jiné domény
  • 2. Odešlete hlavičku Access-Control-Allow-Origin pro všechny prostředky, ke kterým je potřeba přistupovat odkudkoli
  • 3. Udělejte to pomocí webového serveru nebo php
  • 4. Toto záhlaví je odesláno do php hlavičkou příkazu („Access-Control-Allow-Origin: *“)
  • 5. Access-Control-Allow-Origin: *-povolení přístupu ke všem doménám, Access-Control-Allow-Origin: site.ru-pouze doména site.ru
  • 6. Access-Control-Allow-Origin se odesílá na úplný začátek souboru php, a to ještě před výstupem jiných dat (stejně jako jakékoli jiné hlavičky http)
  • 7. „Prostředek“ není jen soubor se značkami html, ale také jakákoli adresa URL, na kterou jde požadavek ajax, například příjem dat json nebo požadavek na přidání řádku do databázové tabulky

A poslední věc, kterou jsem vytáhl samostatně. Ne nadarmo jsem žádal o provedení požadavků z http-stránky. S https nebudete moci načítat data z http z jiného důvodu - smíšený obsah. A web je stále http-site ( aktualizováno: již ne, přesunul web na https)

Zde je to, co vidíte v konzole při pokusu o stejný požadavek z jakéhokoli webu https. Pokud se tedy budete zabývat vloženými widgety nebo něčím podobným, rozhodně musíte na svůj web vložit certifikát ssl.

jQuery.ajax () - vytvoří požadavek na server bez opětovného načtení stránky. Toto je metoda nízké úrovně s velké množství nastavení. Je v centru všeho ajax, který je často snazší pochopit a používat, ale ve srovnání s touto metodou stále poskytuje omezené funkce.

$ .ajax () vrací objekt XMLHttpRequest. Ve většině případů nebudete muset pracovat přímo s tímto objektem, ale je stále k dispozici, pokud potřebujete ručně přerušit požadavek.

Jako argument pro funkci $ .ajax () je předán objekt, který se skládá z párů klíč / hodnota, které se používají k inicializaci a manipulaci s požadavkem.

Žádost Ajaxu má dva případy použití:

jQuery.ajax (url [, nastavení])

Jediným rozdílem od předchozí verze metody je, že vlastnost url zde je součástí nastavení, a nikoli samostatným parametrem.

Seznam nastavení

  1. přijímá(výchozí: závisí na DataType)
    Typ: objekt.
    Při zadání požadavku záhlaví určují platné typy obsahu očekávané od serveru. Hodnoty těchto typů budou převzaty z parametru akceptuje. Následující příklad například uvádí platné vlastní typy:

    $ .ajax ((přijímá: (mycustomtype: "application / x-some-custom-type"), převaděče: ("text mycustomtype": funkce (výsledek) (návrat newresult;)), dataType: "mycustomtype"));

    $. ajax ((

    přijímá: (

    mycustomtype: "application / x-some-custom-type"

    převaděče: (

    "text mycustomtype": funkce (výsledek) (

    vrátit nový výsledek;

    dataType: "mycustomtype"

    } ) ;

  2. asynchronní(výchozí: true)
    Typ: boolean.
    Ve výchozím nastavení jsou všechny požadavky odesílány asynchronně (to znamená, že po odeslání požadavku na server stránka nezastaví svou práci při čekání na odpověď). Pokud potřebujete odesílat požadavky synchronně, nastavte tuto možnost na false. Požadavky mezi doménami a „jsonp“ nelze spouštět synchronně. Synchronní požadavky mohou během provádění požadavku zablokovat prohlížeč.
  3. beforeSend (jqXHR, nastavení)
    Typ: funkce.
    Obsahuje funkci, která bude volána těsně před odesláním požadavku ajax na server. Taková funkce může být užitečná pro úpravu objektu jqXHR (v dřívější verze knihovny (až 1,5), místo jqXHR se používá XMLHttpRequest). Můžete například změnit / určit požadovaná záhlaví atd. Object-jqXHR bude předán funkci jako první argument. Druhým argumentem je nastavení požadavku.
    beforeSend odkazuje na události ajax. Pokud tedy zadaná funkce vrátí hodnotu false, požadavek ajax bude zrušen. Od jQuery-1.5 se volá beforeSend bez ohledu na typ požadavku.
  4. mezipaměti(výchozí: true, false pro dataType "skript" a "jsonp")
    Typ: boolean.
    pokud chcete, aby prohlížeč neukládal ukládaný požadavek do mezipaměti, nastavte tento parametr na hodnotu false. Pokud je parametr nastaven na hodnotu false, bude do adresy URL přidán řetězec „_ =“.
  5. kompletní (jqXHR, textStatus)
    Typ: funkce.
    Funkce, která se má provést vždy, když se dokončí požadavek AJAX (po dokončení úspěchu a chyby). Do funkce jsou předány dva parametry: jqXHR (v dřívějších verzích knihovny (až 1,5) se místo jqXHR používá XMLHttpRequest) a stav provedení požadavku (hodnota řetězce: „úspěch“, „nemodifikovaná“, „chyba“, „timeout“, „abort“ nebo „parsererror“).
    Počínaje jQuery-1.5 můžete k úplnému parametru předat více než jednu funkci, ale řadu funkcí. Všechny funkce budou volány v pořadí, v jakém jsou zadány v tomto poli.
  6. obsah
    Typ: objekt.
    Parametr byl zaveden v jQuery-1.5. Je dán objektem ve formátu (řetězec: regulární výraz) a určuje, jak bude jQuery analyzovat (analyzovat) odpověď ze serveru v závislosti na jeho typu.
  7. typ obsahu
    Typ: boolean nebo řetězec.
    Když je požadavek odeslán na server, data jsou přenášena ve formátu uvedeném v contentType. Výchozí hodnota je 'application / x-www-form-urlencoded; charset = UTF-8 ', což je ve většině případů v pořádku. Pokud tento parametr zadáte explicitně, bude předán serveru (i když tam nebyla odeslána žádná data).
    Od jQuery-1.6 je možné zadat hodnotu false a nenastavit název.
  8. kontext
    Typ: objekt.
    Objekt, který se stane kontextem po provedení požadavku (hodnota předaná této proměnné). Pokud například jako kontext zadáte prvek DOM, pak budou v kontextu tohoto prvku DOM spuštěny také všechny obslužné rutiny požadavků ajax. V tomto příkladu klíčové slovo toto bude obsahovat document.body:

    $ .ajax ((URL: "test.html", kontext: document.body)). done (funkce () ($ (toto) .addClass ("hotovo");));

    $. ajax ((

    URL: "test.html",

    kontext: dokument. tělo

    )). hotovo (funkce () (

    $ (toto). addClass („hotovo“);

    } ) ;

  9. převodníky(výchozí: ("* text": window.String, "text html": true, "text json": jQuery.parseJSON, "text xml": jQuery.parseXML))
    Typ: objekt.
    Parametr byl představen v jQuery-1.5. Určuje, jaké funkce budou použity k převodu hodnot z jednoho typu na druhý.
  10. crossDomain(výchozí: false pro stejnou doménu, true pro požadavky mezi doménami)
    Typ: boolean.
    Parametr byl zaveden v jQuery-1.5. Pokud chcete ve stejné doméně provést požadavek mezi doménami (např. JSONP), nastavte crossDomain na hodnotu true. To například umožňuje provést přesměrování na straně serveru do jiné domény.
  11. data
    Typ: objekt, řetězec nebo pole.
    Data, která mají být přenesena na server. Pokud data nejsou řetězcem, jsou převedena na řetězec dotazu. U požadavků GET jsou data připojena k adrese URL. Objekt musí být složen z párů klíč / hodnota. Pokud je hodnotou pole, pak jQuery uspořádá hodnoty na základě tradičního nastavení. Ve výchozím nastavení se například (foo: ["bar1", "bar2"]) stane & foo = bar1 & foo = bar2.
  12. dataFilter (data, typ)
    Typ: funkce.
    Funkce, která provede předběžné zpracování dat odeslaných serverem, tj. měl by fungovat jako filtr a vrátit vyčištěný řetězec. Této funkci jsou předány dva parametry: zmíněná data a hodnota parametru datový typ... Funkce zadaná v dataFilter by měla vrátit zpracovaná data.
  13. datový typ(výchozí: automaticky detekováno (xml, json, skript nebo html))
    Typ: řetězec.
    Datový typ, ve kterém chcete obdržet odpověď ze serveru. Pokud není nastaveno, jQuery se ho pokusí automaticky detekovat pomocí MIME, který obdrží ze serveru.
  14. chyba
    Typ: funkce
    Funkce, která bude volána, pokud požadavek na server selže. Je vybaven třemi parametry: jqXHR (XMLHttpRequest se používá až do 1,5), řetězec popisující chybu, ke které došlo, a objekt výjimky, pokud existuje. Možné hodnoty pro druhý argument jsou „časový limit“, „chyba“, „nezměněno“ a „parsererror“ (v neočekávaných případech lze vrátit hodnotu null). Od jQuery-1.5 může tento parametr přijímat buď jednu funkci, nebo řadu funkcí.
    Chybová událost nenastane, když dataType je skript nebo JSONP.
  15. globální(výchozí: true)
    Typ: boolean.
    Zodpovědný za fungování globálních událostí požadavku ajax (například ajaxStart nebo ajaxStop). Pokud nastavíte tento parametr na hodnotu false, globální události pro této žádosti nebude volán.
  16. záhlaví
    Typ: objekt.
    Parametr byl zaveden v jQuery-1.5. Zde můžete zadat další záhlaví požadavků (záhlaví). Hodnoty pro toto nastavení budou zadány před voláním funkce beforeSend, ve které lze provést konečné změny záhlaví.
  17. ifModified
    Typ: boolean.
    Pokud je toto nastavení nastaveno na hodnotu true, požadavek bude proveden se stavem „úspěšný“, pouze pokud se odpověď ze serveru liší od předchozí odpovědi. jQuery to ověří odkazem na záhlaví Last-Modified. Počínaje jQuery-1.4 se kromě Last-Modified také kontroluje „etag“ (oba jsou poskytovány serverem a jsou potřebné k upozornění prohlížeče, že požadovaná data ze serveru se od předchozího požadavku nezměnila).
  18. isLocal
    Typ: boolean.
    Parametr byl představen v jQuery-1.5.1 Umožňuje nastavit stav zdroje stránky na místní (jako kdyby používal protokol souboru), i když ho jQuery rozpoznal odlišně. Knihovna rozhodne, že je stránka spuštěna lokálně v případě následujících protokolů: soubor, * -rozšíření a widget. Doporučuje se nastavit hodnotu parametru isLocal globálně - pomocí funkce $ .ajaxSetup () a nikoli v nastavení jednotlivých požadavků ajax.
  19. jsonp
    Typ: řetězec nebo boolean.
    Definuje název parametru, který je přidán do adresy URL požadavku JSONP (ve výchozím nastavení se používá „zpětné volání“). Například nastavení (jsonp: "onJSONPLoad") je převedeno na část adresy URL řetězce "onJSONPLoad =?" ... Od verze 1.5 zadávání false v tomto parametru zabrání přidání na URL další parametr... V takovém případě musíte nastavit hodnotu nastavení jsonpCallback. Například takto: (jsonp: false, jsonpCallback: "callbackName").
  20. jsonpCallback
    Typ: řetězec nebo funkce.
    Definuje název funkce, která bude volána, když server odpoví na požadavek jsonp. Ve výchozím nastavení generuje jQuery pro tuto funkci libovolný název, což je upřednostňovaná možnost usnadňující práci s knihovnou. Jedním z důvodů, proč byste měli zadat vlastní funkci pro zpracování požadavků jsonp, je zlepšit ukládání do mezipaměti požadavků GET.
    Od jQuery-1.5 můžete v tomto parametru specifikovat funkci, aby bylo možné odezvu serveru zpracovat sami. V tomto případě musí zadaná funkce vrátit data přijatá ze serveru (v zadané funkci budou k dispozici v prvním parametru).
  21. metoda (výchozí: „ZÍSKAT“)
    Typ: řetězec.
    Parametr byl zaveden v jQuery-1.9.0 Umožňuje zadat typ požadavku na server („POST“, „GET“, „PUT“)
  22. mimeType
    Typ: řetězec.
    Parametr se objevil v jQuery-1.5.1 V tomto poli můžete určit datový typ, ve kterém se očekává odpověď od serveru místo XHR
  23. Heslo
    Typ: řetězec.
    Heslo pro ověření serveru, je -li vyžadováno.
  24. processData(výchozí true)
    Typ: boolean.
    Ve výchozím nastavení jsou data odeslaná na server převedena z objektu na řetězec dotazu (formát adresy URL: fName1 = hodnota1 & fName2 = hodnota2 & ...) a odeslána jako "application / x-www-form-urlencoded". Pokud potřebujete odeslat dokument DOM nebo jiná data, která nelze převést, nastavte volbu processData na hodnotu false.
  25. scriptCharset
    Typ: řetězec.
    Používá se pouze pro požadavky Ajax GET, dataType může být buď „jsonp“ nebo „script“. Pokud server v doméně třetí strany používá kódování odlišné od vašeho, musíte zadat kódování serveru třetí strany.
  26. statusCode
    Typ: objekt.
    Parametr byl představen v jQuery-1.5.0 Sada párů, ve kterých jsou mapovány prováděcí kódy požadavku na funkce, které budou v tomto případě volány. Například pro kód 404 (stránky neexistují) můžete na obrazovce zobrazit zprávu:

    $ .ajax ((statusCode: (404: function () (alert ("page not found");))));

    $. ajax ((

    statusCode: (

    404: function () (

    alert ("stránka nenalezena");

    } ) ;


    Pokud byl požadavek úspěšný, pak jako parametr, anonymní funkce převezme stejné parametry jako funkce, které zpracovávají úspěšné provedení požadavku (zadané v parametru úspěch), a v případě chyby jsou stejné jako u chybových funkcí.
  27. úspěch (data, textStatus, jqXHR)
    Typ: funkce, pole.
    Funkce, která bude volána v případě úspěšného dokončení požadavku na server. Bere 3 argumenty:
    • data (data) odeslaná serverem a předzpracovaná;
    • řetězec se stavem spuštění (textStatus);
    • objekt jqXHR (ve verzích starších než 1,5 se místo jqXHR používá XMLHttpRequest). Vzhledem k tomu, že jQuery 1.5 namísto jediné funkce může tento parametr převzít řadu funkcí.
  28. Časový limit
    Typ: číslo.
    Čas čekat na odpověď ze serveru v milisekundách. Přepisuje Globální nastavení stejný parametr v $ .ajaxSetup (). Pokud je tento čas překročen, požadavek skončí chybou a dojde k chybové události, která bude mít stav „časový limit“.
    Čas se počítá od okamžiku volání funkce $ .ajax. Může se stát, že v tuto chvíli bude spuštěno několik dalších požadavků a prohlížeč odloží provedení aktuálního požadavku. V takovém případě se časový limit může dokončit, i když ve skutečnosti požadavek ještě ani nebyl spuštěn.
    V jQuery-1.4 a starších, když vyprší časový limit, objekt XMLHttpRequest zadá chybový stav a přístup do jeho polí může vyvolat výjimku. Ve Firefoxu 3.0 a vyšším nebudou požadavky skriptů a JSONP přerušeny, pokud vyprší časový limit. Budou dokončeny i po uplynutí této doby.
  29. tradiční
    Typ: boolean.
    Chcete -li použít tradiční parametry transformace (serializace), nastavte hodnotu tohoto parametru na hodnotu true.
  30. typ(výchozí: „ZÍSKAT“)
    Typ: řetězec.
    Analogicky k parametru metody. Tento parametr se používá v jQuery před 1.9.0
  31. url(výchozí: adresa aktuální stránky)
    Typ: řetězec.
    Určuje adresu, na kterou bude požadavek odeslán.
  32. uživatelské jméno
    Typ: řetězec.
    Případně uživatelské jméno pro autentizaci serveru.
  33. xhr(výchozí: ActiveXObject v IE, XMLHttpRequest v jiných prohlížečích)
    Typ: funkce.
    Funkce, která poskytne objekt XMLHttpRequest. Ve výchozím nastavení je pro prohlížeče IE tento objekt ActiveXObject, jinak je to XMLHttpRequest. Pomocí tohoto parametru můžete vložit vlastní verzi tohoto objektu.
  34. xhrFields
    Typ: objekt.
    Parametr byl zaveden v jQuery-1.5.1 Sada párů (název: hodnota) pro změnu / přidání hodnot odpovídajících polí objektu XMLHttpRequest. Můžete například nastavit jeho withCredentials vlastnost na true, když děláte požadavek mezi doménami:

    $ .ajax ((URL: a_cross_domain_url, xhrFields: (withCredentials: true)));

    $. ajax ((

    URL: a_cross_domain_url,

    xhrFields: (

    withCredentials: true

    } ) ;

Jak již bylo uvedeno výše, $ .ajax () je nejzákladnější metodou a všechny následující metody jsou pouze obálky. Od té doby je velmi málo nutné tuto funkci volat existuje více alternativ vysoká úroveň jako, a. Jsou snáze pochopitelné a používané, i když $ .ajax () je flexibilnější.

Nejjednodušším případem použití by bylo volání $ .ajax () bez zadání parametrů:

$. ajax ();

Obsluha událostí

Nastavení beforeSend, error, dataFilter, success a complete vám umožňuje nastavit obslužné rutiny událostí, které se vyskytují v konkrétních bodech při provádění každého požadavku ajax.

  • před odesláním nastává bezprostředně před odesláním požadavku na server;
  • chyba nastane, pokud je žádost neúspěšná;
  • datový filtr nastane, když data přijdou ze serveru. Umožňuje zpracovat „nezpracovaná“ data odeslaná serverem;
  • úspěch nastává v případě úspěšného dokončení požadavku;
  • kompletní nastane při každém dokončení požadavku.
  • úspěch: funkce () (

    výstraha ( „Data byla úspěšně odeslána.“) ;

    } ) ;

    Pozornost! Výše uvedená nastavení .success (), .error () a.complete () byla přidána do jQuery-1.5 kromě výchozích metod odložených pro nastavení obslužných rutin done (), .fail () a .then (). , počínaje jQuery-1.8, budou tyto tři metody zastaralé.

    Parametr DataType

    Funkce $ .ajax () se dozví o typu dat odeslaných serverem ze samotného serveru (pomocí MIME). Kromě toho je možné osobně naznačit (objasnit), jak by tyto údaje měly být interpretovány. To se provádí pomocí parametru datový typ... Možné hodnoty pro tento parametr:

    • "Xml"- výsledný xml dokument bude k dispozici v textové podobě. Můžete s ním pracovat standardní prostředky jQuery (stejné jako u html dokumentu).
    • "Html"- výsledný html bude k dispozici v textové podobě. Pokud obsahuje ve značkách skripty
      Množství něčeho na serveru site2.ru -

      PHP

      Nyní musíme vytvořit objekt JSON s daty v PHP. Předpokládejme, že máme na serveru site2.ru uložený určitý čítač, vyžádáme si jej z webu site1.ru a získáme pouze číslo (množství něčeho). Všimněte si, že musíme vytvořit objekt JSONP místo běžného objektu JSON.

      // Vytvořte pole s daty, která chceme odeslat json s odpovědí $ data = array ("counter" => 5,); // Přeložte pole na JSON $ json_data = json_encode ($ data); // Nastavte záhlaví kódování a typu obsahu ("Content-type: application / json; charset = utf-8"); // JSONP - ozvěna objektu JSONP $ _GET ["zpětné volání"]. "(". $ json_data. ");";

      Uložte soubor jako counter.php a nahrajte jej na server site2.ru

      JAVASKRIPT

      Nyní musíme zavolat $ .ajax v jQuery, jak je popsáno níže:

      $ (document) .ready (function () ($ .ajax ((type: "GET", url: "http://site2.ru/counter.php?callback=?", dataType: "jsonp", úspěch: funkce (data) ($ (". text. Counter"). html (data.counter);)));));

      Pokud nezadáte funkci zpětného volání, ale napíšete zpětné volání =? - pak se automaticky nahradí název funkce jQuery, ale můžete také explicitně zadat název funkce, například callback = parseFunction.

      Nyní spusťte soubor HTML na webu1.ru. Měli byste obdržet odpověď ze serveru s daty json. Tento ajax pro více prohlížečů můžete také použít pro $ .getJSON, $ .ajax, $ .post a $ .get.

      P.S. Nezapomeňte v příkladu nahradit site2.ru názvem vašeho vzdáleného serveru, na který zadáváte požadavek.

      Pokud máte nějaké dotazy nebo doplňky, napište do komentářů níže.