Ostatnio wypełniałem elektroniczny wniosek na portalu służącemu obywatelowi. Niestety dodawanie załącznika zadziałało po kilku próbach i na trzeciej z kolei przeglądarce. Całe szczęście, że obszerniejsze treści miałem przygotowane i zapisane w dokumencie na dysku. Jednak utrata danych, to chyba jedna ze zmór każdego użytkownika komputera. Łatwiej się pogodzić z kradzieżą kurtki z teatralnej szatni, czy kapci ze szpitalnej sali, niż ze stratą danych.
Na straży formularzy.
Wykorzystamy dziś zdarzenie, które czasem jest używany do podnoszenia ciśnienia internautom. Czyli beforeunload, które powoduje pojawienie się wyskakującego komunikatu przy próbie zamknięcia strony. Ale wykorzystamy je zgodnie z prawem. Kiedyś była możliwość dopasowania treści komunikatu pojawiającego w prompt'cie, obecnie nie ma. Oczywiście jako, że jesteśmy prawilni, to nie będziemy go pokazywać zawsze przy próbie zamknięcia strony, ale tylko kiedy zajdzie taka potrzeba. Za potrzebę uznamy sytuację kiedy w formularzu zaszła jakaś "zmiana". W cudzysłowu, bo wiem nie będziemy wchodzić aż tak w szczegóły zmian - jeśli ktoś doda literę w polu, a następnie ją usunie, to i tak uznamy to za zmianę. Podobnie z wyborem opcji czy klikaniem radio i checkboxów.
Dirty Harrison Form.
Jak zazwyczaj będzie potrzebny HTML i jakiś kod. Testowym HTML będzie formularz z dodanym atrybutem data-isdirty. Jeśli data-isdirty będzie mieć wartość true, to oznacza, że musimy zatrzymać przeładowanie strony, w przeciwnym wypadku możemy zezwolić. Początkowo więc atrybut zostawiamy pusty.
<form data-isdirty>
<fieldset>
<label>1<input type="radio" name="radio" value="1"/></label>
<label>2<input type="radio" name="radio" value="2"/></label>
<label>3<input type="radio" name="radio" value="3"/></label>
</fieldset>
<fieldset>
<label>1<input type="checkbox" value="1"/></label>
<label>2<input type="checkbox" value="2"/></label>
<label>3<input type="checkbox" value="3"/></label>
</fieldset>
<fieldset>
<input type="text" /><br /><textarea></textarea><br />
<select>
<option></option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</fieldset>
<input type="submit" />
</form>
W skrypcie JS natomiast, będziemy obsługiwać tylko formularz z tym atrybutem. Musimy podpiąć się pod dwa zdarzenia: input oraz change. Edge nie obsługuje zdarzenia input na SELECT oraz pól typu radio i checkbox. Podpinamy się więc i badamy czy dotyczy ono jakiegokolwiek z pól formularza, które jest możliwe do edycji poprzez interakcję z użytkownikiem. Jeśli "zmiana" nastąpiła, to ustawiamy wartość atrybutu data-isdirty na true. W ten sposób obsługując zdarzenie beforeunload, wiem, że mamy do czynienia ze zmodyfikowanym formularzem. Aby była jednocześnie możliwość zapisania formularza i uniknięcia komunikatu podczas wyjścia z podstrony, dodajemy obsługę zdarzenia submit. Wtedy wiemy, że nastąpi zapis formularza i możemy przepuścić przez proces przeładowania - ustawiamy więc data-isdirty na false.
const form = document.querySelector("form[data-isdirty]");
form.addEventListener("input", function(e) {
if (
e.target.tagName === "INPUT" ||
e.target.tagName === "SELECT" ||
e.target.tagName === "TEXTAREA"
) {
this.setAttribute("data-isdirty", true);
}
});
form.addEventListener("submit", function() {
this.setAttribute("data-isdirty", false);
});
window.addEventListener("beforeunload", function(e) {
if (document.querySelector('form[data-isdirty="true"]')) {
e.preventDefault();
/* tego wymaga Chrome */
e.returnValue = "";
}
});
A tak wygląda nasz zabezpieczony formularz w działaniu.
Całe szczęście, że udało mi się zapisać ten artykuł... Do przeczytania!
Przydatne linki:
Zdarzenie beforeunload
Zdarzenie input