Bugreport:
Jeg trykker på ‘Tilføj maskine”, udfylder felterne, og trykker '”Gem”. Når jeg så trykker på “tilbage” for at tilføje en ny maskine, så ryger jeg ud i login billedet, og skal strate helt forfra. Hvis jeg trykker på “Frem” igen, kommer jeg ind på listebilledet, og skal finde modulet forfra.
Det er måske en lille fejl, men det koster mig meget tid hver dag.
Mvh Signe
Alle webudviklere er selvfølgelig klar over hvad det er der er galt – der bliver trykket på browserens tilbage-knap, og brugeren forventer at den virker som alle andre knapper i applikationen. Brugeren ser ingen væsentlig forskel på at bruge en web-applikation, og at browse på en hjemmeside. Der ligger med andre ord en udfordring i at understøtte / håndterer det bruger mønster.
Jeg har set mange løsninger, hvor man åbner applikationen op i et nyt browservindue, uden knapper, og på den måde fjerner muligheden for brugeren, eller man deaktiverer browser history via script. Det er for det første svært at gøre noget i den retning, der virker i alle browsere, og det kan kræve at brugeren skal deaktiverer popup-blockere osv.
I mine øjne, er en løsning der blokerer browserens navigation ikke optimal. Man skal udnytte det flow som knapperne giver, og bruge det i applikationen. Det vil give en langt mere brugervenlig applikation.
Jeg har lavet et lille JavaScript objekt, der indeholder en simpel dictionary (JS objekt), som jeg opdaterer på løbende. Dvs. jeg opdaterer objektet med brugerens indtastninger, klik, bevægelse osv. Samtidig serialicerer jeg denne dictionary, og indsætter den efter “#” i url’en. Det smarte er nemlig at man kan sætte location.hash uden at siden bliver postet, men satidig bliver værdien en del af browserens history liste. Hvis man så kan deserialicerer disse værdier i sidens onload event, kan man altså initialicerer sin klientside applikation, når brugeren trykker frem eller tilbage. Andet er der faktisk ikke i det:
// Kræver jQuery
var $state = function() {
// Private objekter
var _dict = {};
var _serialize = function() {
var res = "";
for (var key in _dict) {
res += (res ? "|" : "") + key + "=" + _dict[key];
}
return res;
};
var _deserialize = function(data) {
var items = data.split(/[|#]/g);
for (var i = 0, l = items.length; i < l; i++) {
if (!items[i])
continue;
var kevValue = items[i].split('=');
if (kevValue.length < 2)
continue;
_dict[kevValue[0]] = kevValue[1];
}
};
var _save = function() {
location.hash = _serialize();
};
// Initialicering
$(document).ready(function() {
_deserialize(location.hash);
for (var key in _dict) {
$("#" + key).val(_dict[key]);
}
});
// Public / offentlige objekter
return {
set: function(key, value) {
_dict[key] = value;
_save();
},
get: function(key) {
if (typeof (_dict[key]) == "undefined")
throw new Error("Ingen state med nøglen: " + key);
return _dict[key];
},
hookup: function(id) {
$(id).change(function() {
var $caller = $(this);
$state.set($caller.attr("id"), $caller.val());
});
}
};
} ();
Jeg har for nemhedens skyld lavet en hookup funktion, som man kan kalde med en jQuery søgestreng, og automatisk opdaterer hash værdien, med elementets onshange event. Man kan selvfølgelig lave sine egne handles via de mere generiske metoder get og set.
Det var faktisk ikke andet der skulle til, for at højne bruger oplevelsen for Signe væsentligt.
Code on…