Automatické ukládání a obnova libovolných HTML formulářů pomocí jQuery
MyEgo.cz
Automatické ukládání a obnova libovolných HTML formulářů pomocí jQuery
Pro jednoho klienta dodáváme analyticky i programátorsky hodně zajímavý projekt - Monitoring druhů. Jedná se o sledování parametrů u stovek druhů, přičemž každý druh má nejen velice rozsáhlou, ale také rozdílnou množinu často unikátních parametrů. Realizace je provedena pomocí uživatelské definice formulářů administrátorem systému. Tyto formuláře používají před-definované datové typy, číselníky, našeptávače, subformuláře (včetně neomezeného zanořování) a další prvky. Veškeré hodnoty mohou mít jak 1:1, tak 1:N relace, mohou být povinné či nepovinné. Data z těchto formulářů se ukládají jako XMLType do Oracle 10g.
Samotné řešení XML formulářů je tak zajímavé, že bude předmětem několika dalších článků, ale v tomto budu psát o něčem jiném - automatickém ukládání těchto formulářů při jejich editaci uživatelem.
Automatické ukládání zajišťuje, že složitý formulář, který uživatel může editovat třeba celý den, nezmizí, pokud spadne prohlížeč nebo uživatel zapomene data uložit. Je to podobná funkce jako "obnova dokumentů" ve Wordu.
Vzhledem k tomu, že formulář se vytváří dynamicky (přes AJAX), není možné ukládat jen jeho jednotlivé hodnoty vyplňované uživatelem třeba do cookies či sessions, je nutné uložit celou strukturu dynamicky vytvořeného XHTML / AJAXu, včetně uživatelsky zadávaných hodnot, subformulářů a jiných údajů.
Přímo se zde tedy nabízí uložit kompletní XHTML editované stránky. K tomu slouží pomocná tabulka v Oracle:
CREATE TABLE "MOD_AUTOSAVE" ( "MEMBERID" NUMBER(11,0) NOT NULL ENABLE, "URL" VARCHAR2(250 BYTE) NOT NULL ENABLE, "OBSAH" CLOB, "DATUM" TIMESTAMP (6), CONSTRAINT "MOD_AUTOSAVE_PK" PRIMARY KEY ("MEMBERID") )
Ke každému formuláři je připojena událost, která při změně v INPUT, SELECT či TEXTAREA položkách upozorní uživatele, že by měl uložit data a zároveň zapne časovač myTimeoutFunction()
, který po dalších 30 sekundách provede automatické uložení. Aby se data do pomocné tabulky neukládala zbytečně neustále (i když si třeba uživatel vaří kávu a nejsou žádné změny), je vše vázáno pouze na tuto událost změny hodnot.
function setChangeHandler() { $("input, select, textarea").bind("change", submitFormHandler); } $(document).ready(function(){ setChangeHandler(); }); var submitFormHandler = function() { $("input, select, textarea").unbind("change", submitFormHandler); $("#info").html('<p>Data byla změněna. Nezapomeňte je uložit!</p>'); myTimeout = window.setTimeout(myTimeoutFunction,30000); };
Samotný obsah formuláře pro uložení je načten přes jQuery metodu html()
, jen drobně modifikovanou, protože Firefox v ní nevrací změny provedené uživatelem v INPUT / SELECT / TEXTAREA boxech.
Je tedy použita drobná modifikace této metody pomocí formhtml()
pluginu, která si tyto změny načte:
(function($) { var oldHTML = $.fn.html; $.fn.formhtml = function() { if (arguments.length) return oldHTML.apply(this,arguments); $("input,button", this).each(function() { this.setAttribute('value',this.value); }); $("textarea", this).each(function() { $(this).text(this.value); }); $(":radio,:checkbox", this).each(function() { if (this.checked) this.setAttribute('checked', 'checked'); else this.removeAttribute('checked'); }); $("option", this).each(function() { if (this.selected) this.setAttribute('selected', 'selected'); else this.removeAttribute('selected'); }); return oldHTML.apply(this); }; })(jQuery);
Poté je 30 sekund po uživatelské změně dat zavoláno zaslání načteného formuláře AJAXem na server:
var myTimeoutFunction = function() { $.post( '/ajax-save.php', { data: $('#userdata').formhtml() }, function(result) { $('#info').html('<p>Data byla nahrána do pomocné schránky.</p>'); window.clearTimeout(myTimeout); setChangeHandler(); } ); };
Na straně serverového skriptu se pak jedná jen o triviální načtení dat formuláře z $_POST a jejich uložení do pomocné Oracle tabulky v ajax-save.php
:
<?php include('cfg.php'); global $member; if (!$member->isLoggedIn()) die; $data = postVar('data'); sql_query('INSERT INTO MOD_AUTOSAVE (MEMBERID,DATUM) VALUES ('. $member->getID().','.formatdate(time()).')'); sql_clob('AUTOSAVE', 'OBSAH', 'MEMBERID='.$member->getID(), &$data); ?>
Když se uživatel přihlásí a v pomocné tabulce MOD_AUTOSAVE je nějaký záznam, je mu nabídnuto volitelné pokračování v editaci automaticky uloženého formuláře. Funkčnost je zde opravdu prostá, načte se uložené XHTML a vypíše se.
Při úspěšném uložení formuláře se samozřejmě pomocná AUTOSAVE tabulka promaže.
Tímto principiálně jednoduchým způsobem je možné nabídnout obnovu "ztracených" dat pro libovolně složité formuláře, aniž by bylo dopředu nutné znát jejich strukturu, ukládat hodnoty do cookies či sessions, a složitě rekonstruovat přesný DOM.
Příklady kódu jsou zkráceny, ale idea je zachována.