HTMX: knihovna pro tvorbu stránek pomocí mírně rozšířeného HTML

24. 11. 2022
Doba čtení: 25 minut

Sdílet

 Autor: Depositphotos
Ukážeme si zajímavou knihovnou nazvanou HTMX. Je napsaná v JavaScriptu a umožňuje tvorbu jednodušších webových aplikací a dynamických prezentací, pouze za použití jazyka HTML rozšířeného o několik nových atributů.

Obsah

1. HTMX: knihovna pro tvorbu dynamických stránek založená na hypertextu s rozšířenými možnostmi

2. Hypermedia as the Engine of Application State (HATEOAS)

3. Omezení současného HTML

4. Řešení nabízená projektem HTMX

5. Příklad použití HTMX

6. Praktický příklad

7. Spuštění webového serveru s podporou CGI skriptů

8. Modifikace stránky výměnou celé zvolené značky

9. Server nahrazující zvolenou část HTML stránky HTML kódem

10. Webová aplikace založená na backendu naprogramovaného v jazyku Go

11. Jednoduchý HTTP server naprogramovaný v jazyku Go

12. Otestování stránky s dynamickým obsahem

13. Dynamické stránky se serverem nabízejícím pouze statický obsah

14. Stránka s popisy vybraných programovacích jazyků

15. Specifikace způsobu změny HTML stránky atributem hx-swap

16. Specifikace události, na kterou se má reagovat atributem hx-trigger

17. Další možnosti nabízené knihovnou HTMX

18. Plnohodnotná alternativa pro tvorbu SPA?

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. HTMX: knihovna pro tvorbu dynamických stránek založená na hypertextu s rozšířenými možnostmi

V dnešním článku se seznámíme s knihovnou nazvanou HTMX. Jedná se o knihovnu naprogramovanou v JavaScriptu, která umožňuje tvorbu jednodušších webových aplikací a dynamických prezentací pouze za použití jazyka HTML rozšířeného o několik nových atributů. Tyto nové atributy umožňují, aby se webová aplikace či prezentace zapisovala pouze deklarativním způsobem, tj. v HTML a popř. v CSS, tedy bez explicitního použití JavaScriptu. Podporována je i komunikace se serverem, přičemž je možné použít sémanticky korektní HTTP metody (GET, POST, PUT, DELETE atd.) a výsledek posílaný serverem (typicky plain text nebo fragment HTML) lze deklarativně vložit na zvolené místo ve webové stránce – a to opět bez explicitního volání imperativního JavaScriptového kódu. Knihovna HTMX tedy nabízí alternativní způsob tvorby webových aplikací, který se liší jak od klasického konceptu dotaz→nová stránka, tak i od konceptu používaného v Reactu a dalších podobně koncipovaných knihovnách (i když se v důsledku HTMX k Reactu přibližuje, protože taktéž umožňuje tvorbu SPA).

Poznámka: minifikovaná varianta knihovny HTMX zabere necelých 40kB, tj. jedná se o JavaScriptovou knihovnu spíše menší velikosti. V případě, že se při přenosu používá GZIP, je nutné přenést pouze cca 12kB, což z dnešní perspektivy již není mnoho.

2. Hypermedia as the Engine of Application State (HATEOAS)

V souvislosti s knihovnou HTMX se poměrně často používá zkratka HATEOAS neboli po rozepsání zkratky Hypermedia as the Engine of Application State. Jedná se o jeden z principů, na nichž byla postavena architektura REST, jež se ovšem později posunula poněkud odlišným směrem. HATEOS specifikuje, že klientská aplikace, což je v našem případě webová stránka (resp. SPA) komunikuje s backendem (aplikačním serverem) přes dynamicky poskytované hypermédium. Díky tomu je klient do značné míry oddělen od serveru – není nutné explicitně popisovat komunikační protokol (neexistuje zde striktně vyžadovaná obdoba IDL či JSON schema), klient může být vyvíjen nezávisle na serveru a naopak. V případě HTMX je oddělení ještě větší, protože klient vlastně vůbec nemusí „rozumět“ posílaným datům, na rozdíl od „moderního“ RESTu, kde klient nějakým způsobem data zpracovává a tedy závisí na tom, v jakém formátu jsou data posílána – a každá změna ve schématu může vést k nutnosti změny na straně klienta a naopak.

3. Omezení současného HTML

Autoři dále popsané knihovny HTMX identifikovali čtyři poměrně zásadní omezení značkovacího jazyka HTML (a to včetně poslední verze HTML5), které vývojáře de facto nutí k tomu, aby tato omezení v mnoha případech obcházeli přímým použitím JavaScriptu. A to dokonce i v těch situacích, kdy je JavaScriptový kód použit k operacím, které by v ideálním případě mohly být nabízeny přímo webovým prohlížečem.

Konkrétně se jedná o následující omezení, která, jak je ostatně patrné, spolu do určité míry souvisí:

  1. HTTP požadavky (posílané na server na základě akcí provedených uživatelem) lze vyvolat pouze dvěma ovládacími prvky vytvořenými s využitím značek<a> a <form>, tedy pouze s využitím hypertextového odkazu a formuláře (ve skutečnosti pozapomněli na dvojici map+area a několik dalších drobností, což ovšem na věci nic nemění).
  2. Samotný HTTP požadavek je přitom vyvolán jen dvěma možnými akcemi uživatele – click a submit, tedy kliknutím na hypertextový odkaz popř. odesláním formuláře. Žádné další uživatelské akce k poslání požadavku nevedou (opět pochopitelně za předpokladu, že nepoužijeme JavaScript).
  3. Navíc jsou podporovány pouze dvě HTTP metody, a to konkrétně metodaGET (hypertextový odkaz, formulář) a POST (jen formulář), což omezuje sémantiku operací.
  4. Po odeslání požadavku dojde (společně s příchodem odpovědi) ke změně obsahu celé HTML stránky – celá stránka se tedy nahrazuje stránkou novou, což dosti podstatným způsobem omezuje tvorbu složitějších stránek či aplikací (resp. nutí vývojáře do volání JavaScriptu).
Poznámka: poslední omezení bylo do určité míry obcházeno použitím rámců (frame) a vložených rámců (iframe), což je dnes značně nepopulární technologie.

4. Řešení nabízená projektem HTMX

Všechna čtyři výše uvedená (zásadní) omezení v současnosti používaného značkovacího jazyka HTML jsou v knihovně HTMX řešena, a to takovým způsobem, že jsou do HTML zavedeny nové atributy dostupné u prakticky všech HTML značek (ne zcela všech, týká se to vizuálních značek). Tyto atributy určují, na jaké události má daný prvek zobrazený na webové stránce reagovat (a nemusí se jednat jen o reakce typu click či submit), jaký HTTP požadavek se má poslat na server, jaká HTTP metoda se pro poslání požadavku použije a v neposlední řadě se taktéž specifikuje jaká oblast HTML stránky se má překreslit, tedy nahradit za data získaná ze serveru (to tedy znamená, že se nebude nutně překreslovat celá HTML stránka).

Mezi nové atributy přidané do HTML značek v rámci projektu HTMX patří zejména:

Atribut Stručný popis
hx-trigger specifikace události, která vyvolá dotaz (požadavek) poslaný na HTTP server
hx-request konfigurace toho, jak má vypadat dotaz (požadavek) poslaný na HTTP server
hx-target specifikace oblasti stránky, která se překreslí po přijetí odpovědi
hx-swap hx-swap-oob specifikace, jak se má překreslit daná oblast stránky (zda obsah značky, či značka celá)
hx-get hx-post hx-put hx-delete hx-patch specifikace různých HTTP metod
hx-vals hx-vars hodnoty posílané v požadavku (typicky v JSONu)
Poznámka: jak uvidíme dále, předpokládá se, že odpovědí na HTTP požadavek bude HTML kód popř. čistý text, kterým se nahradí určitá značka na HTML stránce. Stále se tedy pohybujeme v oblasti hypertextu a nikoli dnes primárně prosazované technologie založené na posílání JSONů s jejich následným „přeskládáním“ do vizuální podoby imperativním kódem.

5. Příklad použití HTMX

Podívejme se nyní na velmi jednoduchý demonstrační příklad, který je mimochodem uveden i na stránce https://htmx.org/docs/. Jedná se o standardní ovládací prvek typu „tlačítko“ zapsaný na HTML stránce, ovšem s přidanými novými atributy podporovanými knihovnou HTMX. Všechny nové atributy jsou zvýrazněny:

<button hx-post="/clicked"
    hx-trigger="click"
    hx-target="#parent-div"
    hx-swap="outerHTML"
>
    Click Me!
</button>

Díky těmto novým atributům bylo možné specifikovat následující chování HTML stránky (a to deklarativně, nikoli imperativně):

  1. Po stisku tlačítka myši (click) je na HTTP server poslán HTTP dotaz; konkrétně se bude jednat o dotaz typu POST a koncovým bodem bude „/clicked“
  2. Přečtenou odpovědí (což bude část HTML stránky) bude nahrazen prvek s identifikátorem #parent-div, zatímco zbytek stránky se nebude překreslovat
  3. Nahrazen přitom bude celý zvolený prvek, tedy včetně svého „kořenového“ elementu (dojde k jeho úplné náhradě)
Poznámka: povšimněte si, že jsme definovali nejenom to, jaké informace se mají na HTML stránce zobrazit, ale můžeme zvolit i styl zobrazení (pomocí CSS) a dokonce i „dynamické“ chování stránky. To vlastně znamená, že se bude jednat o plnohodnotnou hypermediální stránku reagující na akce prováděné uživatelem. Všechny tři součásti této HTML stránky jsou přitom zapsány čistě deklarativním stylem, nikoli s využitím imperativního kódu – tvůrce se vůbec nemusí zabývat JavaScriptem atd.

6. Praktický příklad

Vyzkoušejme si nyní koncept, který byl představen v rámci předchozí kapitoly, uplatnit v praxi. Pro tento účel si vytvoříme jednoduchou webovou „aplikaci“, resp. přesněji řečeno (postupně) několik variant takové aplikace. Každá „aplikace“ (a jak uvidíte dále, jsou zde uvozovky skutečně na místě) se skládá ze tří souborů:

  1. HTML soubor, který mj. při otevření ve webovém prohlížeči načítá JavaScriptový soubor htmx.min.js s implementací HTMX. Tento soubor obsahuje kód HTML stránky bez imperativního kódu (vše – i definice akce a reakce na ni – je zapsáno deklarativně).
  2. Již výše zmíněný soubor htmx.min.js (vždy poslední dostupná verze).
  3. Spustitelný soubor cgi-bin/answer se skriptem, který bude volán HTTP serverem.

Adresářová struktura prvního demonstračního příkladu bude v té nejjednodušší podobě vypadat následovně:

.
├── basic_example1.htm
├── cgi-bin
│   ├── answer
├── get_htmx
└── htmx.min.js
Poznámka: v adresáři s projektem je, jak jste si zajisté mohli povšimnout, uložen i skript nazvaný get_htmx, který po svém spuštění stáhne poslední minifikovanou verzi knihovny HTMX. Tento skript je tedy nutné spustit ještě před inicializací webového serveru (v repositáři HTMX přímo nemám, neboť je vhodné si vždy stáhnout poslední verzi, nehledě na licence).

Nyní se podívejme na soubor basic_example1.htm. Jedná se o statickou HTML stránku, která načítá htmx.min.js (zvýrazněná část). Kromě toho tato HTML stránka obsahuje definici tlačítka, po jehož stisku se přes HTTP metodu POST zavolá skript /cgi-bin/answer, který vrátí nějaká data (HTML kód). Tento HTML kód je vložen do HTML značky s identifikátorem „answer-div“:

<html>
    <head>
        <title>HTMX - elementary example</title>
        <script type="text/javascript" src="htmx.min.js">
        </script>
    </head>
    <body>
        <button hx-post="/cgi-bin/answer"
                hx-trigger="click"
                hx-target="#answer-div">
            Retrieve answer!
        </button>
 
        <div id="answer-div">
            Answer...?
        </div>
    </body>
</html>
Poznámka: povšimněte si, že na této HTML stránce není ani jeden JavaScriptový (imperativní) kód.

Nyní se podívejme na obsah skriptu /cgi-bin/answer. Pro jednoduchost je tento skript naprogramován v Pythonu a po svém spuštění odešle na standardní výstup HTTP hlavičku 200 OK, za níž následuje tělo (payload) obsahující pouze text „42“. Jak hlavička, tak i tělo jsou HTTP serverem poslány do webového prohlížeče:

#!/usr/bin/env python3
 
import sys
print('200 OK\r\n\r\n42')
Poznámka: použití CGI skriptů může mnohým čtenářům připadat jako již dávno překonaná technologie (což je v mnoha oblastech zajisté pravda), ale tento příklad je zde uveden zejména pro ilustraci možností HTMX i v těch oblastech/firmách, v nichž nejsou k dispozici profesionální tvůrci webových aplikací.

7. Spuštění webového serveru s podporou CGI skriptů

Nyní v adresáři s výše popsaným projektem spustíme webový server, u kterého navíc budeme muset povolit spouštění CGI skriptů. Pro jednoduchost použijeme server dodávaný společně se standardní knihovnou Pythonu. Pozor: tento server není určen pro produkční nasazení (a už vůbec ne s takto povolenými CGI skripty otevřenými „celému světa“). Pro lokální testování nám však může toto řešení dostačovat:

$ python3 -m http.server --cgi 9000
 
Serving HTTP on 0.0.0.0 port 9000 (http://0.0.0.0:9000/) ...

Ve webovém prohlížeči otevřeme stránku dostupnou na adrese http://localhost:9000:

127.0.0.1 - - [22/Nov/2022 15:42:52] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [22/Nov/2022 15:42:52] code 404, message File not found
127.0.0.1 - - [22/Nov/2022 15:42:52] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [22/Nov/2022 15:43:39] "GET /basic_example1.htm HTTP/1.1" 200 -
127.0.0.1 - - [22/Nov/2022 15:43:39] "GET /htmx.min.js HTTP/1.1" 200 -

Obrázek 1: Stránka se seznamem poskytovaných souborů poskytovaná HTTP serverem.

Zvolíme stránku http://localhost:9000/basic_e­xample1.htm:

Obrázek 2: Stránka basic_example1.htm otevřená ve webovém prohlížeči.

Po stisku tlačítka na stránce se provede dotaz na server:

127.0.0.1 - - [22/Nov/2022 15:44:59] "POST /cgi-bin/answer HTTP/1.1" 200 -

A stránka se na ploše prohlížeče upraví – zobrazí se odpověď serveru:

Obrázek 3: Stránka, jejíž část (pouze část) se překreslila s odpovědí serveru.

8. Modifikace stránky výměnou celé zvolené značky

Nyní HTML (HTMX?) stránku nepatrně upravíme – přidáme další atribut k tlačítku, který říká, že odpověď dodaná serverem má nahradit celou zvolenou značku, což v tomto konkrétním případě znamená celý odstavec (včetně značky div):

<div id="answer-div">
    Answer...?
</div>

Upravená stránka bude vypadat následovně – modifikovaná část je zvýrazněna:

<html>
    <head>
        <title>HTMX - elementary example</title>
        <script type="text/javascript" src="htmx.min.js">
        </script>
    </head>
    <body>
        <button hx-post="/cgi-bin/answer"
                hx-trigger="click"
                hx-target="#answer-div"
                hx-swap="outerHTML">
            Retrieve answer!
        </button>
 
        <div id="answer-div">
            Answer...?
        </div>
    </body>
</html>

Otestujme si, co se nyní stane po otevření této stránky a stisku tlačítka na ní:

Obrázek 4: Stránka před stiskem tlačítka.

Obrázek 5: Stránka po stisku tlačítka.

A takto HTML stránku interpretuje prohlížeč – povšimněte si, že skutečně došlo k nahrazení celého odstavce za pouhý text:

Obrázek 6: Tatáž stránka, ovšem zobrazená v Inspectoru.

9. Server nahrazující zvolenou část HTML stránky HTML kódem

To, že je možné nahradit celou zvolenou značku kódem získaným ze serveru nám umožňuje, aby se část „dynamického“ renderingu stránky prováděla na jednom místě – na serveru (třeba s využitím šablonovacích systémů atd.). Ostatně si to můžeme snadno otestovat. Nejprve změníme cestu k CGI skriptu:

<html>
    <head>
        <title>HTMX - elementary example</title>
        <script type="text/javascript" src="htmx.min.js">
        </script>
    </head>
    <body>
        <button hx-post="/cgi-bin/answer2"
                hx-trigger="click"
                hx-target="#answer-div"
                hx-swap="outerHTML">
            Retrieve answer!
        </button>
 
        <div id="answer-div">
            Answer...?
        </div>
    </body>
</html>

A taktéž upravíme příslušný skript takovým způsobem, že se vrátí HTML kód, konkrétně odstavec se stylem:

#!/usr/bin/env python3
 
import sys
print('200 OK\r\n\r\n<div style="color:red">42</div>')

Výsledek:

Obrázek 7: Obsah stránky před stiskem tlačítka.

Obrázek 8: Obsah stránky po stisku tlačítka a překreslení místa na stránce, kde se nacházel odstavec.

Samozřejmě nejsme omezeni pouze na použití odstavců. Můžeme do stránky dynamicky přidat například nadpis:

<html>
    <head>
        <title>HTMX - elementary example</title>
        <script type="text/javascript" src="htmx.min.js">
        </script>
    </head>
    <body>
        <button hx-post="/cgi-bin/answer3"
                hx-trigger="click"
                hx-target="#answer-div"
                hx-swap="outerHTML">
            Retrieve answer!
        </button>
 
        <div id="answer-div">
            Answer...?
        </div>
    </body>
</html>

Upravený skript, který vrátí nadpis, bude vypadat následovně:

#!/usr/bin/env python3
 
import sys
print('200 OK\r\n\r\n<h1>42</h1>')

Výsledky:

Obrázek 9: Obsah stránky před stiskem tlačítka.

Obrázek 10: Obsah stránky po stisku tlačítka a překreslení té oblasti na stránce, kde se nacházel odstavec.

Poznámka: nyní bude adresář, který bude používán HTTP serverem, vypadat následovně:
.
├── basic_example1.htm
├── basic_example2.htm
├── cgi-bin
│   ├── answer
│   ├── answer2
│   └── answer3
├── get_htmx
├── htmx.min.js
├── outer_div1.htm
└── outer_div2.htm
 
1 directory, 9 files

10. Webová aplikace založená na backendu naprogramovaného v jazyku Go

Všechny předchozí demonstrační příklady byly kvůli jednoduchosti založeny na použití CGI skriptů, což je technologie, která sice stále má své uplatnění (intranety, různé projekty z oblasti zpracování dat atd.), ovšem ne vždy se jedná o ideální řešení pro tvorbu moderních veřejně dostupných webů. Ukažme si tedy nyní poněkud odlišný přístup, jenž je založený na backendu naprogramovaného v jazyku Go, jenž je pro tyto účely téměř ideální. Struktura adresáře s projektem je jednoduchá:

.
├── basic_example1.htm
├── get_htmx
├── htmx.min.js
└── httpServer.go
 
0 directories, 4 files

Nalezneme zde tyto soubory:

  • HTML stránka dodávaná serverem
  • Skript pro stažení knihovny html.min.js (v minifikované podobě)
  • Samotná knihovna html.min.js
  • HTTP server naprogramovaný v jazyku Go

Nejdříve se podívejme na HTML stránku, která opět obsahuje značky s atributy z knihovny HTMX. Povšimněte si, že adresa endpointu, jemuž budeme posílat dotaz HTTP metodou POST je „/answer“:

<html>
    <head>
        <title>HTMX - elementary example</title>
        <script type="text/javascript" src="htmx.min.js">
        </script>
    </head>
    <body>
        <button hx-post="/answer"
                hx-trigger="click"
                hx-target="#answer-div">
            Retrieve answer!
        </button>
 
        <div id="answer-div">
            Answer...?
        </div>
    </body>
</html>
Poznámka: v adresáři s projektem je opět uložen i skript nazvaný get_htmx, který po svém spuštění stáhne poslední minifikovanou verzi knihovny HTMX. Tento skript je tedy nutné spustit ještě před překladem a spuštěním webového serveru.

11. Jednoduchý HTTP server naprogramovaný v jazyku Go

Samotná implementace HTTP serveru (jenž mimochodem dokáže obsluhovat dotazy paralelně) je vytvořena v jazyku Go a používá pouze standardní knihovnu tohoto jazyka. To tedy znamená, že nemusíme instalovat další podpůrné knihovny typu Gorilla Web Toolkit atd. Server dokáže odpovídat na dotazy na trojici endpointů, přičemž pro endpointy „/“ a „/htmx.min.js“ se vrátí obsah souborů načtených z disku, kdežto pro endpoint „/answer“ se odpověď vygeneruje programově, konkrétně zápisem MIME typu odpovědi, HTTP kódu v hlavičce a těla odpovědi (ovšem pro jednoduchost nezpracováváme žádné parametry požadavku ani jeho tělo):

package main
 
import (
        "fmt"
        "log"
        "net/http"
)
 
func indexPageHandler(writer http.ResponseWriter, request *http.Request) {
        http.ServeFile(writer, request, "basic_example1.htm")
}
 
func htmxHandler(writer http.ResponseWriter, request *http.Request) {
        http.ServeFile(writer, request, "htmx.min.js")
}
 
func answerHandler(writer http.ResponseWriter, request *http.Request) {
        writer.Header().Set("Content-Type", "application/html")
        writer.WriteHeader(http.StatusOK)
        fmt.Fprint(writer, `<h1>42</h1>`)
}
 
func startHttpServer(address string) {
        log.Printf("Starting server on address %s", address)
 
        http.HandleFunc("/", indexPageHandler)
        http.HandleFunc("/htmx.min.js", htmxHandler)
        http.HandleFunc("/answer", answerHandler)
        http.ListenAndServe(address, nil)
}
 
func main() {
        startHttpServer(":8080")
}

Tento server přeložíme a spustíme příkazem:

$ go run httpServer.go
 
2022/11/23 12:52:48 Starting server on address :8080

12. Otestování stránky s dynamickým obsahem

Po spuštění serveru naprogramovaného v jazyce Go můžeme velmi snadno zjistit, jak se bude chovat takto vytvořená „webová aplikace“:

Obrázek 11: Stránka poskytnutá serverem pro endpoint „/“.

Obrázek 12: Modifikovaný obsah stránky po stisku tlačítka, poslání dotazu na server a odpovědi serveru.

13. Dynamické stránky se serverem nabízejícím pouze statický obsah

V některých případech je možné se zcela obejít bez sofistikovaného backendu, protože všechny informace, které se mají uživatelům zobrazit (i v interaktivní podobě) jsou dostupné ve formě statických dat poskytovaných HTML serverem. Příkladem může být webová prezentace, na jejíž úvodní stránce se nachází ikony vybraných programovacích jazyků. Uživatel si zde může jeden z těchto jazyků vybrat a stránka by měla na základě této akce zobrazit podrobnější informace o tomto jazyku. Jedná se přitom o statické informace, které není nutné dynamicky vytvářet na základě dotazu. V takovém případě můžeme (pochopitelně) použít HTMX, ovšem namísto sofistikovaného backendu nám bude postačovat libovolný HTTP server poskytující statická data – HTML stránky, obrázky a textové soubory.

Obrázek 13: Obsah HTML stránky s nabídkou ikon vybraných programovacích jazyků.

Obsah adresáře se statickými daty, které budeme používat, vypadá následovně:

apl_logo.png
APL.txt
Clojure.png
Clojure.txt
C.png
C.txt
get_htmx
Go.png
Go.txt
Java.png
Java.txt
languages.htm
languages2.htm
languages3.htm
Python.png
Python.txt
Rust.png
Rust.txt

14. Stránka s popisy vybraných programovacích jazyků

Podívejme se nyní, jak by mohla vypadat stránka obsahující ikony programovacích jazyků, ovšem s tím, že po kliknutí na nějakou ikonu má dojít k zobrazení podrobnějších informací o vybraném jazyku. Stránka obsahuje sérii obrázků, přičemž po kliknutí na nějaký obrázek pošle webový prohlížeč HTTP GET požadavek na server (například se bude jednat o požadavek na poslání souboru „C.txt“). Po přijetí odpovědi se získané tělo odpovědi zapíše do odstavce s identifikátorem „language“. Toto chování je plně popsáno atributy hx-get, hx-trigger a hx-target:

<html>
    <head>
        <title>HTMX - elementary example</title>
        <script type="text/javascript" src="htmx.min.js">
        </script>
    </head>
    <body>
        <img src="apl_logo.png" hx-get="APL.txt"     hx-trigger="click" hx-target="#language" />
        <img src="Clojure.png"  hx-get="Clojure.txt" hx-trigger="click" hx-target="#language" />
        <img src="C.png"        hx-get="C.txt"       hx-trigger="click" hx-target="#language" />
        <img src="Go.png"       hx-get="Go.txt"      hx-trigger="click" hx-target="#language" />
        <img src="Java.png"     hx-get="Java.txt"    hx-trigger="click" hx-target="#language" />
        <img src="Python.png"   hx-get="Python.txt"  hx-trigger="click" hx-target="#language" />
        <img src="Rust.png"     hx-get="Rust.txt"    hx-trigger="click" hx-target="#language" />
        <div id="language">
        </div>
    </body>
</html>

Samotný obsah textových souborů obsahuje krátký popis jazyka zkopírovaný z Wikipedie. Následuje příklad popisku jazyka APL uloženého v souboru „APL.txt“:

APL (named after the book A Programming Language) is a programming language developed in the 1960s by Kenneth E. Iverson. Its central datatype is the multidimensional array. It uses a large range of special graphic symbols to represent most functions and operators, leading to very concise code. It has been an important influence on the development of concept modeling, spreadsheets, functional programming, and computer math packages. It has also inspired several other programming languages.

Obrázek 14: Po kliknutí na ikonu jazyka Go se zobrazí stručný popis tohoto jazyka.

15. Specifikace způsobu změny HTML stránky atributem hx-swap

Po přijetí dat ze serveru je možné určit, jakým způsobem se mají tato data zobrazit na HTML stránce. Pro tento účel slouží atribut hx-swap, který jsme sice již několikrát použili, ale ve skutečnosti nám nabízí ještě další možnosti:

hx-swap Význam
innerHTML data se uloží do zvoleného uzlu (již známe)
outerHTML data zcela nahradí zvolený uzel (již známe)
beforebegin data se vloží před uzel
afterbegin data se vloží před první poduzel zvoleného uzlu (lze tak vytvořit sérii divů atd.)
beforeend data se vloží za poslední poduzel zvoleného uzlu
afterend data se vloží za uzel
delete cílový uzel se smaže
none nic se neprovede, dotaz tedy pouze změnil stav na serveru
Poznámka: díky hodnotám before/after begin/end lze relativně snadno realizovat například chat apod.

Otestujme si, co se stane ve chvíli, kdy použijeme atribut hx-swap=„afterend“. V tomto případě se budou na stránku přidávat další a další textové informace o zvoleném jazyku (což nebude příliš čitelné – lepší by bylo posílat přímo HTML značky odstavců):

<html>
    <head>
        <title>HTMX - elementary example</title>
        <script type="text/javascript" src="htmx.min.js">
        </script>
    </head>
    <body>
        <img src="apl_logo.png" hx-get="APL.txt"     hx-trigger="click" hx-target="#language" hx-swap="afterend" />
        <img src="Clojure.png"  hx-get="Clojure.txt" hx-trigger="click" hx-target="#language" hx-swap="afterend" />
        <img src="C.png"        hx-get="C.txt"       hx-trigger="click" hx-target="#language" hx-swap="afterend" />
        <img src="Go.png"       hx-get="Go.txt"      hx-trigger="click" hx-target="#language" hx-swap="afterend" />
        <img src="Java.png"     hx-get="Java.txt"    hx-trigger="click" hx-target="#language" hx-swap="afterend" />
        <img src="Python.png"   hx-get="Python.txt"  hx-trigger="click" hx-target="#language" hx-swap="afterend" />
        <img src="Rust.png"     hx-get="Rust.txt"    hx-trigger="click" hx-target="#language" hx-swap="afterend" />
        <div id="language">
        </div>
    </body>
</html>

Obrázek 15: Několik popisků, které byly spojeny v rámci jediného odstavce. Výsledek v tomto případě samozřejmě není příliš čitelný.

16. Specifikace události, na kterou se má reagovat atributem hx-trigger

V atributu hx-trigger jsme prozatím použili hodnotu clicked, což znamená, že stránka reagovala na stisk tlačítka myši nad nějakým obrázkem. Ve skutečnosti je však možné do tohoto atributu vložit i další typ události, například mouseenter (přejetí myší po obrázku). Další podporované typy událostí lze najít například na stránce https://www.javatpoint.com/javascript-events.

Zkusme tedy specifikovat reakci na událost typu mouseenter (pouhé přejetí kurzorem myši do obrázku). Je to snadné:

<html>
    <head>
        <title>HTMX - elementary example</title>
        <script type="text/javascript" src="htmx.min.js">
        </script>
    </head>
    <body>
        <img src="apl_logo.png" hx-get="APL.txt"     hx-trigger="mouseenter" hx-target="#language" />
        <img src="Clojure.png"  hx-get="Clojure.txt" hx-trigger="mouseenter" hx-target="#language" />
        <img src="C.png"        hx-get="C.txt"       hx-trigger="mouseenter" hx-target="#language" />
        <img src="Go.png"       hx-get="Go.txt"      hx-trigger="mouseenter" hx-target="#language" />
        <img src="Java.png"     hx-get="Java.txt"    hx-trigger="mouseenter" hx-target="#language" />
        <img src="Python.png"   hx-get="Python.txt"  hx-trigger="mouseenter" hx-target="#language" />
        <img src="Rust.png"     hx-get="Rust.txt"    hx-trigger="mouseenter" hx-target="#language" />
        <div id="language">
        </div>
    </body>
</html>

Výsledek bude nyní vypadat následovně (na statickém obrázku se špatně ukazuje dynamické chování):

Obrázek 16: Nyní stránka reaguje již na pouhé přejetí myši do plochy obrázku.

17. Další možnosti nabízené knihovnou HTMX

Mezi některé další možnosti, které jsou knihovnou HTMX nabízeny, patří:

ict ve školství 24

  1. možnost informovat uživatele o tom, že se komunikuje se serverem
  2. dotazy lze na server posílat pravidelně (polling) a měnit tak dynamicky informaci o stavu
  3. větší množství dotazů lze synchronizovat
  4. možnost použití přechodů (vizuálních atd.) definovaných v CSS
  5. podpora pro Web Sockety
  6. podpora pro SSE (Server Sent Events)
  7. u libovolné značky (značek) lze specifikovat, že ji nemá HTMX modifikovat (tedy například se omylem nepřepíše titulek stránky)

18. Plnohodnotná alternativa pro tvorbu SPA?

Knihovna HTMX se stává poměrně oblíbenou, zejména v týmech, které nejsou specializovány na tvorbu webových aplikací s využitím (dnes) moderních frameworků. O oblíbenosti HTMX ostatně vypovídá i počet hvězdiček na GitHubu. Nicméně se nabízí otázka, zda HTMX skutečně dokáže nahradit plnohodnotné webové aplikace, typicky SPA (Single Page Application), vytvářené například s využitím Reactu, Vue.js atd. Nutno říci, že možnosti HTMX jsou v některých ohledech omezené, a to konkrétně na realizaci vylepšeného mechanismu pro HTTP dotazy a odpovědi s reakcí stránky na odpovědi. Ovšem například přesun prvků na stránce apod. se již v HTMX nedá jednoduše provést a je nutné sáhnout k jiným mechanismům. Dobrou zprávou je, že kombinace HTMX s JavaScriptem na jediné stránce je možná a vlastně i bezproblémová (z tohoto pohledu se nejedná o framework, ale o poměrně úzce zaměřenou knihovnu).

19. Repositář s demonstračními příklady

Demonstrační příklady napsané v HTML, Pythonu a Go, byly uloženy do Git repositáře, který je dostupný na adrese https://github.com/tisnik/pre­sentations. Jednotlivé demonstrační příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý (dnes již velmi rozsáhlý) repositář:

# Příklad Stručný popis Adresa
1 cgi-based/basic_example1.htm tlačítko s akcí definovanou přes HTMX https://github.com/tisnik/pre­sentations/blob/master/htmx/cgi-based/basic_example1.htm
2 cgi-based/basic_example2.htm využití atributu hx-swap=„outerHTML“ https://github.com/tisnik/pre­sentations/blob/master/htmx/cgi-based/basic_example2.htm
3 cgi-based/outer_div1.htm využití atributu hx-swap=„outerHTML“, volání odlišného cgi-bin skriptu https://github.com/tisnik/pre­sentations/blob/master/htmx/cgi-based/outer_div1.htm
4 cgi-based/outer_div2.htm využití atributu hx-swap=„outerHTML“, volání odlišného cgi-bin skriptu https://github.com/tisnik/pre­sentations/blob/master/htmx/cgi-based/outer_div2.htm
5 cgi-based/get_htmx skript pro získání knihovny htmx.js https://github.com/tisnik/pre­sentations/blob/master/htmx/cgi-based/get_htmx
6 cgi-based/cgi-bin/answer cgi-bin skript naprogramovaný v Pythonu https://github.com/tisnik/pre­sentations/blob/master/htmx/cgi-based/cgi-bin/answer
7 cgi-based/cgi-bin/answer2 cgi-bin skript naprogramovaný v Pythonu vracející celý odstavec https://github.com/tisnik/pre­sentations/blob/master/htmx/cgi-based/cgi-bin/answer2
8 cgi-based/cgi-bin/answer3 cgi-bin skript naprogramovaný v Pythonu vracející nadpis https://github.com/tisnik/pre­sentations/blob/master/htmx/cgi-based/cgi-bin/answer3
       
9 go-server/get_htmx skript pro získání knihovny htmx.js https://github.com/tisnik/pre­sentations/blob/master/htmx/go-server/get_htmx
10 go-server/basic_example1.htm tlačítko s akcí definovanou přes HTMX https://github.com/tisnik/pre­sentations/blob/master/htmx/go-server/basic_example1.htm
11 go-server/httpServer.go HTTP server naprogramovaný v jazyku Go https://github.com/tisnik/pre­sentations/blob/master/htmx/go-server/httpServer.go
       
12 static/languages.htm HTML stránka nabídkou programovacích jazyků a jejich popisu https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/languages.htm
13 static/languages2.htm úprava předchozí stránky – připojení textu, nikoli jeho náhrada https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/languages2.htm
14 static/languages3.htm dynamická změna stránky při najetí myši na logo nějakého jazyka https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/languages3.htm
15 static/APL.txt stručný popis programovacího jazyka APL https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/APL.txt
16 static/Clojure.txt stručný popis programovacího jazyka Clojure https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/Clojure.txt
17 static/C.txt stručný popis programovacího jazyka C https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/C.txt
18 static/Go.txt stručný popis programovacího jazyka Go https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/Go.txt
19 static/Java.txt stručný popis programovacího jazyka Java https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/Java.txt
20 static/Python.txt stručný popis programovacího jazyka Python https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/Python.txt
21 static/Rust.txt stručný popis programovacího jazyka Rust https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/Rust.txt
22 static/apl_logo.png logo programovacího jazyka APL https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/apl_logo.png
23 static/Clojure.png logo programovacího jazyka Clojure https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/Clojure.png
24 static/C.png logo programovacího jazyka C https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/C.png
25 static/Go.png logo programovacího jazyka Go https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/Go.png
26 static/Java.png logo programovacího jazyka Java https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/Java.png
27 static/Python.png logo programovacího jazyka Python https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/Python.png
28 static/Rust.png logo programovacího jazyka Rust https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/Rust.png
29 static/get_htmx skript pro získání knihovny htmx.js https://github.com/tisnik/pre­sentations/blob/master/htmx/sta­tic/get_htmx

20. Odkazy na Internetu

  1. Dynamic Web Pages Without JavaScript? – Intro to HTMX
    https://www.youtube.com/wat­ch?v=CWSmP3LSILo
  2. htmx: Writing JavaScript to Avoid Writing JavaScript, by Carson Gross
    https://www.youtube.com/wat­ch?v=u2rjnLJ1M98
  3. Carson Gross – REST, HATEOAS & Django – It's OK to not use JSON… or Javascript
    https://www.youtube.com/watch?v=L_UWY-zHlOA
  4. htmx.org/dist
    https://unpkg.com/browse/htmx­.org@1.7.0/dist/
  5. intercooler.js
    https://intercoolerjs.org/
  6. htmx – GitHub repositář
    https://github.com/bigsky­software/htmx
  7. why should I use htmx ?
    https://www.reddit.com/r/djan­go/comments/v4yqxi/why_shou­ld_i_use_htmx/
  8. _hyperscript
    https://hyperscript.org/
  9. alpine.js
    https://alpinejs.dev/
  10. HATEOAS
    https://en.wikipedia.org/wiki/HATEOAS
  11. Django, HTMX and Alpine.JS: A Match Made In Heaven
    https://dev.to/nicholas_moen/what-i-learned-while-using-django-with-htmx-and-alpine-js-24jg
  12. Single-page application
    https://en.wikipedia.org/wiki/Single-page_application

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.