Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

Translate to English… Ins Deutsche übersetzen…

Formuláře a HTML5 - co mi ještě chybí

Pracovat s webovým formulářem na straně JavaScriptu se poměrně snadno může stát očistcem. Nebo jak se nazývá ta věc na čištění záchodové mísy. Přitom za všechno může jedno nešťastné rozhodnutí.

Mějme jednoduchý formulář

<form id=myform>
        <input type=text name=query>
        <input type=submit value="Vyhledat">
</form>

K jeho jednotlivým prvkům přistoupíme přes vlastnost elements:

var form = document.getElementById('myform');
var query = form.elements.query.value;
// pochopitelně také form.elements['query'].value

A iterovat nad prvky lze cyklem for:

for (var i = 0; i < form.elements.length; i++) {
        alert(form.elements[i].value);
}

Z historických důvodů lze vlastnost elements v příkladech vynechat, neboť jednotlivé prvky se mapují přímo do objektu form. Takže by fungovalo i form.query.value, form.length nebo form[i].value. Což se záhy ukáže jako nemilé. Formulářové prvky totiž přepisují nativní metody a proměnné objektu form. Například metoda submit(), která je klíčová pro AJAXové odeslání formuláře, se stane nedostupnou, pokud formulář obsahuje prvek nazvaný submit. A uznejte, že to je zrovinka název pro odesílací tlačítko jako dělaný. Pokud by tedy formulář vypadal takto

<form id=myform>
        <input type=text name=query>
        <input type=submit name=submit value="Vyhledat">
</form>

nebude jej možné příkazem form.submit() odeslat, místo toho JavaScript zařve „form.submit is not a function“ a má pravdu, form.submit není funkce ale objekt HtmlInputElement. Dobrá, dáme si pozor a nebudeme formulářové prvky nazývat submit.

(prozradím trik, jak by formulář šlo odeslat i v tomto případě: document.createElement('form').submit.call(form))

Jenže název submit není tím jediným, kterému se musíme vyhnout. Prvek pojmenovaný elements způsobí, že form.elements nebude očekávaná kolekce a výše uvedené příklady skončí chybou. Název length zase znemožní nad kolekcí iterovat. A tak by se dalo pokračovat, nativních prvků třeba DOM Firefoxu definuje hodně přes stovku. Pro zajímavost uvádím seznam jen těch jednoslovných (tj. vynechávám nodeName nebo innerHTML):

action, attributes, blur, children, dir, draggable, elements, encoding, enctype, focus, id, lang, length, method, name, normalize, prefix, reset, spellcheck, style, submit, target, title

Bylo by skvělé, kdyby se HTML5 dokázalo s tímto nešvarem vypořádat. Zatím jsem ve specifikaci nic takového nenašel.

Podobně mi chybí možnost, jak v obsluze události onsubmit zjistit, kterým tlačítkem byl formulář odeslán. Triviální a užitečná věc a jak složitě se musí řešit.

<form id=myform onsubmit="kterým tlačítkem byl odeslán?">
        <input type=hidden name=id value="123">
        <input type=submit name=save value="Uložit">
        <input type=submit name=delete value="Smazat">
</form>

Řeším to tak, že odchytávám událost click jednotlivých tlačítek a název prvku ukládám do vlastní proměnné formuláře. O něco jednodušší je využít bublání a odchytávat click přímo na formuláři. Nicméně v HTML5 tohle už nebude fungovat spolehlivě, protože prvek může být umístěn i mimo strom formuláře a přiřazen k němu atributem form. Bylo by tedy fajn, kdyby HTML5 zavedlo vlastnost například form.submitter, který by vracela název odesílajícího tlačítka.

p. s. Nette Framework s těmito situacemi počítá a snaží se je v rámci možností řešit za programátora

napsáno 12. 8. 2010 | shlédnuto 5938x | nahoru


Komentáře RSS 2.0 komentářů » přidat

avatar

#1 Daniel Steigerwald nový

Zjistit tlačítko lze. Ne však pomocí čistého Javascriptu, protože form eventy: submit, focus, blur a reset nebublají. Kdyby jo, použil bys jednoduše event.target.
Chytřejší javascriptové knihovny (a jQuery) tohle řeší. Pro focus/blur použijí eventy náhradní nebo capture fázy. Tohle však u submit ani reset použít nelze. Interně to třeba jQuery řeší tak, že po registraci $(‚form‘).live(‚sub­mit‘, fn') skutečně odchytává click, pak no následně volá na všech parentech, a tím simuluje bublání.
Mají tam však bug, takže i když submit buble, a currentTarget funguje, tak target se korektně nastaví pouze v IE. Chtěl sem jim napsat fix, ale musel sem se spokojit s nahlášením bugu, protože sem po ruce neměl potřebný „očistec“.
Shrnuto, nativně to HTML5 řešit nemůže, protože to je zpětně kompatibilní pragmatická „specifikace“ (na rozdíl od idealistické XHTML2).
Řeší to však knihovny, a jQuery ten bug dříve či později opraví též.

Posláno 12. 8. 2010 v 19.04 | Odpovědět
Na komentář reagoval [9] David Grudl
avatar

#2 Daniel Steigerwald nový

Co se týká prvku elements a mapování names na form, mám pocit že jde o prehistorický pozůstatek DOM0.
Koukám teď, že nejenom YUI3 ale i jQuery zcela zbytečně tuto prehistorickou kolekci stále používají. jQuery v metodě http://api.jquery.com/serializeArray/
Mootools například elements nikdy nepoužívali. Serializovat přeci můžeš libovolný element, obsahující formulářové prvky. Mimochodem, výstup té jQuery metody je dost nepraktický, raději z formuláře vyrobím objekt http://pastie.org/1088700, a ten pak pošlu na server jako JSON, kde se mi nabinduje na existující třídy. Plochá querystring struktura je na prd, pokud chceš na server odeslat celé objektové grafy.
V Nette bych pak místo .elements použil .getElementsBy­TagName(‚*‘). Šlape to všude a žádného přepisování se není třeba obávat.
Co se týká mapování na form. O tom vím, ale nikdy sem to neřešil, protože sem nikdy nepoužíval syntetický submit (nepíšu weby, ale aplikace). Triku pomocí call bych se bál, ale pokud to funguje všude, nech to tak. (jen je třeba to testovat)

Posláno 12. 8. 2010 v 19.20 | Odpovědět
avatar

#3 Daniel Steigerwald nový

Jestli chceš vidět dobrou implementaci (třeba pro inspiraci pro Nette), mrkni se na http://github.com/…ini/nwevents

Posláno 12. 8. 2010 v 19.42 | Odpovědět

#4 vojta nový

Je to drobnost, ale všechny atributy HTML prvků by měly být v uvozovkách, kodéra to dráždí! :-)

Posláno 12. 8. 2010 ve 20.15 | Odpovědět
avatar

#5 Jan Tichý http://www.phpguru.cz nový

#4 vojta: Neměly. (Ajajaj, to bude zase flame.)

Posláno 12. 8. 2010 ve 20.32 | Odpovědět
avatar

#6 Patrik Votoček http://patrik.votocek.cz nový

#4 vojta: Neměly. Ale můžou.

Posláno 12. 8. 2010 ve 21.15 | Odpovědět

#7 v6ak http://v6ak.profitux.cz nový

Ono by to asi šlo řešit bez úderu do zpětné kompatibility. Ale, na druhou stranu, dost hnusně. Mám pocit, že je možné nějakému objektů přiřadit ekvivalent __call. (Na phpfashion mi asi budete rozumět.)
Víte, kam mířím? Mohly by tu být metody jako getAction(), getLength() apod. Pokud by někdo čistě náhodou použil takto blbý název, dostal by onen element ono „__call“. Ale, na druhou stranu, pokud by takový element měl svoje id (například), šlo by třeba odesílat formulář pomocí document.getE­lementById(„fo­o“)(), měl-li bych <button type="submit" name="submit" id="foo">Odeslat. Takže, je to trošku vyhánění satana ďáblem.

Posláno 12. 8. 2010 ve 21.38 | Odpovědět
avatar

#8 David Grudl http://davidgrudl.com nový

#4 vojta: do uvozovek dávají atributy jen méněcenní kodéři a tlusté ženy!

Posláno 13. 8. 2010 v 6.38 | Odpovědět
Na komentář reagoval [10] vojta
avatar

#9 David Grudl http://davidgrudl.com nový

#1 Daniel Steigerwald: Dane, stačí právě probublávání click a tím pádem to řešit lze.

Posláno 13. 8. 2010 v 6.39 | Odpovědět

#10 vojta nový

#8 David Grudl: „Always Quote Attribute Values
Attribute values should always be enclosed in quotes
http://www.w3schools.com/…tributes.asp
Jestli je tady kroužek opozice vůči standardům, mělo by to být uvedeno v hlavičce webu ;-)

Posláno 30. 8. 2010 v 15.04 | Odpovědět
Na komentář reagoval [11] David Grudl
avatar

#11 David Grudl http://davidgrudl.com nový

#10 vojta: w3schools.com není standard, ale web soukromé společnosti. Standard najdeš tady nebo tady.

Posláno 30. 8. 2010 v 16.47 | Odpovědět
Na komentář reagoval [12] vojta

#12 vojta nový

#11 David Grudl: OK. Díky za odkazy. Na prvním místě se používání uvozovek výslovně vyžaduje, na druhém se připouští i zápis bez nich. Nevím tedy, jak někteří přišli na to že by se uvozovky psát „neměly“.
Opravdu mi připadá čistší zápis
<a href="#" title="Klikni na mě" name="odkaz123" id="odkaz123" />
než
<a href="#" title="Klikni na mě" name=odkaz123 id=odkaz123 />
a vůbec nerozumím, proč nekonzistentní 2. verzi zápisu někdo považuje za „méněcennou“. Osobně v ní vidím samé nevýhody a divím se, že se nikomu neekluje míchání názvu proměnné s její hodnotou. Zdar.

Posláno 6. 9. 2010 v 16.08 | Odpovědět
Na komentář reagoval [13] vojta

#13 vojta nový

#12 vojta: Davide, teď vidím, že tvůj vlastní parser automaticky přidává hodnotám atributů uvozovky (v mém původním příspěvku u 2. odkazu nejsou uvozovky u atributů name a id).
Tak tohle je dokonalý vlastňák :-D :-D

Posláno 6. 9. 2010 v 16.12 | Odpovědět
Na komentář reagoval [14] David Grudl
avatar

#14 David Grudl http://davidgrudl.com nový

#13 vojta: upravil jsem tvůj komentář, aby tam uvozovky nebyly. Obě HTML specifikace připouštějí možnost za určitých okolností uvozovky vynechat, čti pozorněji. A také tu nikdo neříkal, že by se psát neměly. Tohle téma prosím uzavřeme.

Posláno 6. 9. 2010 v 19.28 | Odpovědět

#15 v6ak http://v6ak.profitux.cz/ nový

Taky jsem pro, sice tu už asi nebude živá diskuze, ale myslím, že tato diskuze jen odvádí pozornost od tématu.

Posláno 6. 9. 2010 ve 20.18 | Odpovědět

Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.

Výtah na začátek článku na první komentář

Názory čtenářů v diskusích nejsou názory provozovatele webu, a ten za jejich obsah neodpovídá.

phpFashion © 2004, 2012 David Grudlo webu

Pokud není uvedeno jinak, podléhá obsah těchto stránek licenci Creative Commons BY-NC-ND Creative Commons License BY-NC-ND

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.