Autor Zpráva
hypot
Profil
Dotazy na odeslání e-mailu pomocí PHP jsou evergreenem zdejších dotazů, jak jsem si všiml, prakticky všechny však řeší problémy se samotným odesláním či s náležitostmi odesílaného e-mailu. Já mám však jiný problém, se kterým si nevím rady, protože ačkoli na internetu jsou tisíce návodů na odeslání e-mailu z HTML formuláře pomocí funkce mail v PHP, nikde (já jsem tedy vůbec nic nenašel) není ani zmínka o tom, jak to začlenit do stránek uživatelsky přívětivým způsobem.

Učebnicové texty praví, že do atributu action HTML formuláře je třeba zadat jméno (adresu) nějakého serverového skriptu, který údaje z formuláře zpracuje. Například <form action="email.php" method="post">. Klasický návod na sestavení PHP skriptu na odeslání údajů z formuláře pak končí něčím jako echo "Vaše zpráva byla odeslána". Jenže když se těmi návody řídím a stisknu ve formuláři tlačítko odeslání, e-mail se sice odešle, ale v prohlížeči vzápětí zmizí doposud načtená stránka s formulářem a je nahrazena zcela prázdnou bílou stránkou, na níž je zcela nahoře jen věta "Vaše zpráva byla odeslána" (a v adresním řádku prohlíče je adresa dosavadní stránky nahrazena adresou onoho serverového skriptu). To je z hlediska uživatele samozřejmě zcela šokující výsledek, takže je zřejmé, že takto se to nepoužívá. Jenže co se tedy používá? Jak se to dělá, aby se v prohlížeči neobjevila jen prázdná stránka s pouhou větou nahoře?

Konkrétně by se mi nejvíc zamlouvalo, jak je to řešeno na css-tricks.com/examples/WebsiteChangeRequestForm, kde po odeslání formuláře samotný formulář ze stánky zmizí a je nahrazen oznámením o úspěšném odeslání, přičemž sama stránka zůstává stále načtená jinak bez jakékoli změny. To však jistě není univerzální řešení, jelikož uživatel by například mohl (při určité situaci) chtít onen formulář využít ještě jednou a tudíž by jej potřeboval zobrazit znovu (prázdný).

Zkrátka mi jde o to, jak propojit formulář na stránce se skriptem tak, aby uživatel po použití (odeslání) formuláře dál mohl používat (např. dočíst) stránku, na níž se dotyčný formulář nachází, a aby se nezměnila adresa stránky v adresním řádku prohlížeče (tj. nebyla nahrazena adresou skriptu). Předpokládám, že existuje víc postupů, takže by mě zajímaly všechny (pokud jich není moc). Děkuji. (P.S. Dotaz jsem vložil do sekce Problémy v začátcích.)
Keeehi
Profil
hypot:
Předně je třeba pochopit, že odeslání formuláře je v podstatě stejné, jako kliknutí na odkaz. Tudíž aby jsi zůstal na stejné stránce, musíš buď mít v action odkaz na tu samou stránku (případně ho můžeš vynchat) nebo když action bude vést jinam, tak po odeslání přesměrovat zpět. První varianta je jednodušší pro implementaci zobrazení zprávy pro odeslání. Druhá zase zajistí, že se formulář znovu neodešle v případě, že by uživatel znovu načetl stránku (ctrl+R).
Ať tak či onak, odeslání formuláře způsobí přechod na jinou stránku (i když cílem může být ta samá), takže se ztratí stav té nynější. Pokud je tedy formulář někde níže tak nebude vidět, jelikož ze zobrazí vršek cílové stránky, jako u normálního odkazu. Stejně jako u odkazů jde řešit pozici zobrazení pomocí kotev.

Celé je to způsobené tím, že formulář se chová jako odkaz. Pokud nechceš přijít o stav stránky, nesmíš ho odeslat. To zvládne zajistit javascript. Vhodným kódem se dá zajistí, že těsně před tím, než se formulář odešle, javascript tuto akci zruší. No a pak už je na tobě, co se bude dít dál. O vše už se teď musí postarat javascript. Vezme tedy data z formuláře a AJAXem je odešle na server. Dostane od něj odpověď a nějak vhodně upraví stránku (třeba skryje trn formulář).

Poznámka o přístupnosti. Doporučuji nebýt závislý na javascriptu. Odeslat formulář by mělo jít i bez něj. Javascript by měl uživatelům jen více zpříjemnit používání jinak funkčního webu.
Proto bych doporučil nejdříve implementovat řešení pomocí klasického odesílání formuláře, přesměrování a kotev. Ono samo o sobě bude fungovat velmi dobře. No a následně tuto implementaci rozšířit o AJAXové odesílání.


Pro úplnost ještě dodám, že formulář jde (stejně jako odkaz) odeslat do rámu. Po odeslání se tedy nemění stav hlavní stránky, ale jen stav stránky načtené v tom rámu. Jde o takový pseudo AJAX. Případně samotný formulář může být načten v iframu a jeho odeslání způsobí jen změnu stavu iframu a ne celé stránky.
Celé to tu uvádím jen pro úplnost. S rámy je potřeba pracovat opatrně, jelikož mají své neduhy.
_es
Profil
Keeehi:
Pokud nechceš přijít o stav stránky, nesmíš ho odeslat. To zvládne zajistit javascript.

Môže ho aj odoslať do iframe či frame na stránke (čo neskôr aj spomínaš), do nového okna, či do existujúceho iného okna - vhodne zvoleným atribútom target. JavaScript nie je jediná možnosť, v istých prípadoch má nejaké nedostatky či obmedzenia.
hypot
Profil
No, já to rady nějak vyzkouším, jen mám ještě upřesňující dotazy:

musíš buď mít v action odkaz na tu samou stránku (případně ho můžeš vynchat)
To znamená, že skript na odeslání formuláře musí být součástí stránky samé? A jak potom prohlížeč pozná, že má ten skript zpracovat (respektive předat ke zpracování), když bude odkaz v action vynechaný?

Vezme tedy data z formuláře a AJAXem je odešle na server
Mně jde momentálně o PHP funkci mail. Ta jde také AJAXem?

Proto bych doporučil nejdříve implementovat řešení pomocí klasického odesílání formuláře, přesměrování
Po pravdě řečeno, já to zatím (tj. jen v HTML a CSS) mám tak, že po kliknutí na e-mailovou adresu se zobrazí do té doby skrytý div s formulářem (který překrývá část stránky pod ním) a představoval bych si to tak, že uživatel vyplní a odešle formulář, načež se mu v tom samém divu zobrazí zpráva o odeslání, načež pak uživatel ručně div sám kliknutím na křížek zavře a má před sebou stránku, jak ji viděl před tím, než pojal úmysl odeslat zprávu. To by s přesměrováním ale nešlo, že? Proč vůbec nemůžu spoléhat na javascript? Vždyť jen málo lidí ho má vypnutý, nebo ne?
Keeehi
Profil
hypot:
To znamená, že skript na odeslání formuláře musí být součástí stránky samé?
Přesně tak.

A jak potom prohlížeč pozná, že má ten skript zpracovat (respektive předat ke zpracování), když bude odkaz v action vynechaný?
Když formuláři chybí action, tak se prostě odesílá na adresu na které právě je, jelikož je to jediná adresa kterou zná.

Mně jde momentálně o PHP funkci mail. Ta jde také AJAXem?
To jsou v důsledku dvě věci. PHP zpracovává data a odesílá mail nezávisle na tom, jak mu ta data byla doručena. Je jedno, zda spuštění PHP scriptu bylo zapříčiněno odesláním formuláře nebo AJAX požadavku.
Jinak AJAX není nic úplně speciálního. Je to jen pěkné pojmenování pro obyčejnou techniku v javasvriptu, jak odesílat požadavky na pozadí.

To by s přesměrováním ale nešlo, že?
Přesně tak jak jsi to popsal by to nešlo. Ale dá se vytvořit něco, co se bude chovat velmi podobně. A to je přece lepší záložní varianta než že to bez javascriptu nebude fungovat vůbec.

Proč vůbec nemůžu spoléhat na javascript? Vždyť jen málo lidí ho má vypnutý, nebo ne?
Čísla neznám, navíc se liší web od webu. Jedním důvodem je přístupnost. Ztěžuješ práci postiženým lidem, kteří už tak nemají procházení webu jednoduché a musejí používat speciální software, který si s javascriptem neporadí. Obecně s ním mají problém i vyhledávače, i když situace se už mění.
Ale ono ani tak nejde o tyto skupiny. Dávno ke pryč doba, kdy jediným javascriptem běžícím na stránce byl ten tvůj. Dnes se jednak dost často spoléháš na knihovny tratích stran, takže to nemáš 100% pod kontrolou, no ale hlavně ti do stránky hrabou rozšíření v prohlížích. No a není v tvých silách si nainstalovat všechny a otestovat, zda náhodou nekolidují s tvým kódem.
Javascript obecně může prostě selhat a je dobré mít záložní řešení pro případ že se tak stane.
_es
Profil
hypot:
Proč vůbec nemůžu spoléhat na javascript?
Podstatný je aj tak serverový skript, ktorý mail naozaj odošle. JS môže byť len nejaké zlepšenie použiteľnosti. Nie je preto rozumné, aby bol, v tomto prípade, nutná podmienka.
hypot
Profil
Zatím jsem vyzkoušel variantu přesměrování formuláře do skrytého iframu, což krásně funguje v tom smyslu, že se nic nikam nepřesměruje a stránka s formulářem zůstává stále načtená, nicméně to má vadu, že po odeslání formuláře tímto způsobem v něm zůstávají stále vyplněná pole. Takže jsem se bez javascriptu stejně neobešel, abych mohl resetovat formulář a zobrazit pod formulářem zprávu o odeslání. (Mně použití javascriptu nevadí, protože okno (skrytý div) s formulářem se zobrazí po kliknutí na e-mailovou adresu a i když javascript fungovat nebude, ona e-mailová adresa je stejně pořád k dispozici).

Teď chci zkusit ještě tu variantu s AJAXem, ale ještě mi není pár věcí jasných:
a) jednak nevím, jak (javascriptem) zrušit odeslání formuláře;
b) pak mi ještě víc není jasné, jak zajistím, aby se zpráva o úspěšném odeslání zobrazila tam, kde chci, pokud bude vyvolána PHP scriptem. V té první variantě se skrytým iframem jsem to udělal tak, že po odeslání formuláře se spustila javascriptová funkce, která mimo jiné vytvořila odstavec s textem o úspěšném odeslání zprávy a připojila jej na konec formuláře (javascriptová manipulace s DOM). Jenže toto řešení se mi nezdá nejlepší, protože takto vytvořená zpráva o úspěšném odeslání se zobrazí vždy, bez ohledu na to, zda zpráva skutečně byla odeslána. Lepší by tedy bylo zobrazení zprávy dát až jako podmínku odeslání, což musím dát do PHP scriptu, jenže když napíšu něco jako if (mail(...)) {echo "Zpráva byla odeslána"}, není mně vůbec jasné (poněvadž s PHP mám minimum zkušeností), kde na stránce se vlastně ta zpráva zobrazí, respektive jak docílit toho, aby se zobrazila tam, kde chci (tj. např. na konci nebo začátku formuláře), a taky, jak ji zformátuju pomocí CSS.
Keeehi
Profil
hypot:
že po odeslání formuláře tímto způsobem v něm zůstávají stále vyplněná pole.
A právě proto bych to neodesílal do skrytého rámu, ale normálně. Když se neobejdeš bez javascriptu, pak to vůbec nemusíš řešit.

není mně vůbec jasné, kde na stránce se vlastně ta zpráva zobrazí,
Nikde. Přide jako datová odpověď javascriptu, který ten požadavek odeslal. Proto je v ajaxu právě ta callback funkce. Jako parametr se jí právě předá to, co ten ajaxově načítaný script "zobrazí". Tedy javascript obdrží data a je už jen na něm, co s nimi udělá. Klidně je pak může přidat na konec toho formuláře jak chceš.
hypot
Profil
Díky za rady, už se mi to podařilo sestavit.

Ještě mám dotaz k té variantě, kde je skript přímo na stránce a po odeslání formuláře se znovu načte tatáž stránka. Jak v takovém případě vyřešit zobrazení zprávy o úspěšném odeslání?
Keeehi
Profil
Tak jedno z řešení ke tam, kde chceš aby se zpráva zobrazila i odesílat email.
.. HTML ..
<?php
if (mail(.......)) {
    echo 'email odeslán';
} else {
    echo 'něco se pokazilo';
}
?>
.. HTML ..

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: