Článek vyšel na serveru Interval.cz.
Pokud máme vytvořit dlouhý formulář, je možné ho rozdělit na několik stránek, abychom uživatele nevylekali a neodradili je od vyplňování.
Pokud se vyplněné hodnoty jednotlivých stránek rozhodneme přenášet na server, musíme pro ně zvolit vhodné úložiště. Vhodným místem jsou skrytá formulářová pole, protože jsou přímo svázána s vyplňovaným formulářem, jejich nevýhodou ale je, že se data neustále přenášejí tam a zpátky. Vyplněné hodnoty je možné ukládat také rovnou do databáze (do záznamu označeného ve zvláštním sloupci jako neúplný). Nevhodným místem pro uložení jsou běžné session proměnné, protože znemožňují vyplňování více formulářů najednou. Při zkombinování session proměnných se skrytým formulářovým polem je ale použít můžeme – stačí, když vyplněná data budeme ukládat do prvku pole a identifikátor tohoto prvku si budeme přenášet ve skrytém formulářovém poli.
<?php session_start(); $posledni_stranka = 1; if (!$_POST) { $stranka = 0; $registrace = array(); } else { $stranka = intval($_POST["stranka"]); $form_id = (isset($_POST["form_id"]) ? intval($_POST["form_id"]) : count($_SESSION["registrace"])); $registrace = &$_SESSION["registrace"][$form_id]; $chyba = ""; // uložení vyplněných hodnot foreach ($_POST as $key => $val) { if ($key != "form_id" && $key != "zpet" && $key != "stranka") { $registrace[$key] = $val; } } if ($_POST["zpet"]) { $stranka--; } else { // kontrola vyplněných hodnot switch ($stranka) { case 0: if (!strlen($_POST["jmeno"])) { $chyba .= "Jméno nesmí být prázdné.\n"; } break; case 1: if (!check_email($_POST["email"])) { $chyba .= "Vyplňte prosím e-mail.\n"; } if (!$chyba && !mysql_query("INSERT INTO uzivatele (jmeno, email) VALUES ('" . mysql_real_escape_string($registrace["jmeno"]) . "', '" . mysql_real_escape_string($registrace["email"]) . "')")) { $chyba = "Data se nepodařilo uložit."; } if (!$chyba) { header("Location: ok.php"); exit; } break; } if (!$chyba) { $stranka++; } } } // vypsání formuláře echo "<form action='' method='post'>\n"; if ($_POST) { echo "<input type='hidden' name='form_id' value='$form_id' />\n"; echo "<input type='hidden' name='stranka' value='$stranka' />\n"; if ($chyba) { echo "<p>$chyba</p>\n"; } } switch ($stranka) { case 0: echo 'Jméno: <input name="jmeno" value="' . htmlspecialchars($registrace["jmeno"]) . '" />'; break; case 1: echo 'E-mail: <input name="email" value="' . htmlspecialchars($registrace["email"]) . '" />'; break; } echo "\n<input type='submit' value='" . ($stranka < $posledni_stranka ? "Další" : "Dokončit") . "' />\n"; if ($stranka) { echo "\n<input type='submit' name='zpet' value='Zpět' />\n"; } echo "Strana: " . ($stranka + 1) . "/" . ($posledni_stranka + 1) . "\n"; echo "</form>\n"; ?>
Viz check_email.
V části vypsání formuláře se vypíše aktuální stránka formuláře a tlačítka pro pohyb po stránkách formuláře. Tlačítko Další je před tlačítkem Zpět proto, aby bylo výchozí – jejich vizuální pořadí lze prohodit stylem. Pokud uživatel formulář odešle, tak se data uloží do prvku pole v session proměnné. Pokud se uživatel nechtěl vrátit na předchozí stránku, tak se vyplněné hodnoty zkontrolují a pokud jsou v pořádku, tak se přejde na další stránku. Na poslední stránce se provede přesměrování na skript informující o úspěšném vyplnění a uložení hodnot formuláře.
Před tím, než vícestránkový formulář začneme vytvářet, bychom si měli uvědomit, jakou pro to vlastně máme motivaci. Je formulář moc dlouhý a my nechceme uživatele odradit od jeho vyplňování? Nebo se podoba dalších kroků liší podle toho, co uživatel vyplnil v dříve? Nebo chceme, aby se první stránka formuláře rychle stáhla? U první a s vyvinutím určitého úsilí i u druhé motivace můžeme stránkování vytvořit na straně klienta v JavaScriptu. Tím zároveň zrychlíme odezvy při přechodu mezi stránkami formuláře, což je dobrou protiváhou ke třetí motivaci. Zpracování na serveru bude stejné jako u obyčejného formuláře, uživatelům s vypnutým JavaScriptem jednoduše zobrazíme všechny stránky formuláře najednou.
<form action="" method="post"> <div id="stranka-0"> Jméno: <input name="jmeno" value="<?php echo htmlspecialchars($_POST["jmeno"]); ?>" /> </div> <div id="stranka-1"> E-mail: <input name="email" value="<?php echo htmlspecialchars($_POST["email"]); ?>" /> </div> <script type="text/javascript"> var stranka = 0; var posledni_stranka = 1; function stranka_prechod(f, posun) { var chyba = ''; if (posun > 0) { switch (stranka) { case 0: if (!f['jmeno'].value) { chyba += 'Jméno nesmí být prázdné.\n'; } break; case 1: if (!check_email(f['email'].value)) { chyba += 'Vyplňte prosím e-mail.\n'; } break; } if (chyba) { alert(chyba); } else if (stranka == posledni_stranka) { return true; } } if (!chyba) { document.getElementById('stranka-' + stranka).style.display = 'none'; stranka += posun; document.getElementById('stranka-' + stranka).style.display = ''; document.getElementById('zpet').disabled = !stranka; document.getElementById('dalsi').value = (stranka == posledni_stranka ? 'Dokončit' : 'Další'); document.getElementById('stranka-cislo').innerHTML = stranka + 1; } return false; } for (var i=1; i <= posledni_stranka; i++) { document.getElementById('stranka-' + i).style.display = 'none'; } document.write('<input type="button" id="zpet" value="Zpět" onclick="stranka_prechod(this.form, -1);" disabled="disabled" />\n'); document.write('<input type="submit" id="dalsi" value="Další" onclick="return stranka_prechod(this.form, 1);" />\n'); document.write('Strana: <span id="stranka-cislo">1</span>/' + (posledni_stranka + 1) + '\n'); </script> <noscript><p><input type="submit" value="Dokončit" /></p></noscript> </form>
Tlačítka pro přechod mezi stránkami formuláře budeme zobrazovat vždy obě, u tlačítka Zpět pouze budeme nastavovat jeho zakázanost, u tlačítka Další zase jeho popis. Funkce stranka_prechod
zkontroluje při přechodu vpřed vyplněné hodnoty a na poslední stránce dovolí formulář odeslat. V jiném případě skryje starou stránku formuláře a zobrazí novou. Kontrolu hodnot v JavaScriptu musíme brát samozřejmě jen jako službu pro uživatele a na serveru si musíme kvůli bezpečnosti a konzistenci data zkontrolovat znovu.
Jako uživateli mi vícestránkové formuláře dvakrát příjemné nejsou, ale když už k nim provozovatel webu sáhne, měly by být vytvořeny s ohledem na pohodlí uživatele. Především by mělo fungovat vyplňování více formulářů najednou a pokud to je možné, přechody mezi stránkami by měly být co nejrychlejší. To oba popsané způsoby splňují.
Diskuse je zrušena z důvodu spamu.