Autor Zpráva
joe
Profil
Ahoj,

nějakou dobu jsem hledal, ale nedozvěděl jsem se moc aktuálních informací na tohle téma a proto ho vytvářím i pro případné další zájemce a zajímalo by mě, jak jsme na tom dneska s ukládáním stavu AJAXových aplikací a na jakém principu to vlastně funguje.

Požadavek - například při AJAXovém stránkování chci také umožnit možnost vrácení se zpět tlačítkem v prohlížeči. Jaké mám možnosti jak to udělat? Zkoumal jsem kódy některých pluginů a fungovaly (asi) tak, že vzaly obsah nově načtené stránky a uložily ho do cache. Poté spuštěným časovačem kontrolovaly změnu fragmentu v URL (část za #) a pokud k ní došlo, obsah webu změnily.

V novějších prohlížečích by měla existovat událost onhashchange, takže časovač už nebude v některých případech potřeba -> zdá se mi zbytečné aby na stránce pořád běžel nějaký časovač, netestoval jsem, ale nebude to stránku po čase nějak zpomalovat?

Pak tu už máme storage, které bysme mohli využít.


Nemáte někdo nějaké efektivní řešení, kam by bylo možné nahlédnout jak to pořádně udělat?
Witiko
Profil
joe:
Část prohlížečů podporuje onhashchange event, stejně tak je možné využít v případě podpory onpopstate event spojený s HTML5 history api.
joe
Profil
Witiko:
Díky za odpověď, ale nějak si s tím nevím rady. Můžeš mě nasměrovat jak bych to měl udělat, pokud bych chtěl od následujícího kódu, aby když kliknu na odkaz "druhy" (to se objeví text 'druhy' v divu a v URL se objeví #druhy) a pak kliknu na tlačítko zpět v prohlížeči, tak jsem měl v tom divu zase text 'prvni' jako při načtení? Nějak nevím jak k čemu mi v tom případě je ten objekt pro historii v HTML5.

<!DOCTYPE html>
<html><body>

<script type="text/javascript">

function anchor(x) {
	window.location.hash=x;
	document.getElementById('content').innerHTML = x;
	
	//var historyObj = window.history;
	//historyObj.pushState();
	
	return false;
}

/*
if ("onhashchange" in window) {
	alert("The browser supports the hashchange event!");
}
*/

</script>

<div id="content">
první
</div>

<a href="#" onclick="return anchor('druhy');">druhy</a>
<a href="#" onclick="return anchor('treti');">treti</a>
Witiko
Profil
joe:
Při kliknutí na tlačítko zpět se spustí funkce, kterou připojíš jako posluchače na onhashchange event. Tzn.:
location.hash = "druhy";
onhashchange = function() {
  if(!location.hash.length) alert("prvni!");
};
Po spuštění tohoto kódu a kliknutí na zpět se spustí v podporovaných prohlížečích alert.

Objekt pro historii v HTML5 nabízí jiný přístup k problému (už jsme rozebírali). Umožňuje docílit toho samého s tím, že se vůbec nepracuje s hashem, ale manipuluje se s adresou v adresním řádku (s cross-domain omezeními) přičemž každé adrese - stavu aplikace - je přiřazen i javascriptový objekt, který je možné na klientské straně číst pro zjištění aktuálního stavu. Výhoda je v tom, že adresa v adresním řádku může být plně validní adresou funkční i bez javascriptu, což s hashem ne tak docela platí. Umožňuje to koexistenci ajaxové navigace a klasické Web 1.0 odkazové navigace na stejném systému adres. Většina moderních webů použijí v podporovaných prohlížečích html5 history api a ve starších pak hash. Obojí funkcionalitu pak spojuje například knihovna History.js.

History.js gracefully supports the HTML5 History/State APIs (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles and replaceState. Supports jQuery, MooTools and Prototype. For HTML5 browsers this means that you can modify the URL directly, without needing to use hashes anymore. For HTML4 browsers it will revert back to using the old onhashchange functionality.

Tím nenabádám k jejímu použití. Osobně jsem víc než kdo jiný zastáncem vlastních řešení šitých na míru projektu namísto frameworků a knihoven, jež se snaží uspokojit všechny.
joe
Profil
Witiko:
Po spuštění tohoto kódu a kliknutí na zpět se spustí v podporovaných prohlížečích alert.
To mi je ještě jasný, já jen nechápu, jak místo (v tomhle případě) toho vyhození alertu načíst ten původní obsah. Tedy aby se na té stránce v tom obsahovém divu zase objevil text "prvni" (když v URL se to změni na "#prvni"). Asi tomu nějak nerozumím :)
Fruiko
Profil *
[#5] joe Zkus tenhle videocast.

http://www.zajtra.sk/dev/videocast-nauc-jquery-11-ajax-2-hd/236-clanok.html

Možná budeš potřebovat i díl před...
Witiko
Profil
joe:
Stavovost aplikace si musíš vyřešit sám, hash ti jenom umožňuje detekovat v jakém stavu se právě nacházíš.
joe
Profil
Witiko:
No jo, ale to je to o co mi tu jde :-) Pak zas nechápu k čemu mi je to HTML5 history API, protože když několikrát změním fragment, v prohlížečích (Opera, Chrome, Firefox, IE8+) můžu používat šipky <- a -> bez toho, abych se dostal na jinou adresu (právě se jen mění ten fragment, který je možné odchytit v té události onhashchange - z toho tedy poznám v jakém stavu jsem).

Jde mi o to, jakým způsobem ukládat data tak, abych je nemusel při změně fragmentu znovu tahat přes AJAX (to pravděpodobně myslí Fruiko a to určitě nechci), přijde mi to zbytečné, protože už jsem ty data měl jednou zobrazené a když bych je znovu načítal, už by nemusely být jako předtím.

Přesně tak, jak to chci, tak to dělá i Twitter, stačí otevřít jeden profil, přejít na druhý a když se vrátím tlačítkem zpět, vrátí se mi ten původní profil - oni tam sice nový AJAX požadavek mají, ale ne na konkrétní data - příspěvky apod. A to nevím kam ukládají.
Witiko
Profil
joe:
Pak zas nechápu k čemu mi je to HTML5 history API, protože když několikrát změním fragment
S HTML5 history API neměníš fragment, tam měníš celou adresu. Buď použiješ HTML5 history API nebo změnu fragmentu. Jsou to dva rozdílné přístupy sloužící stejnému účelu - zachování stavovosti aplikace přes adresu.

abych je nemusel při změně fragmentu znovu tahat přes AJAX“, „A to nevím kam ukládají.
Stačí posílat vhodné http hlavičky a při vyslání AJAX požadavku dostaneš data obratem z cache prohlížeče.
joe
Profil
Witiko:
Stačí posílat vhodné http hlavičky a při vyslání AJAX požadavku dostaneš data obratem z cache prohlížeče.
Jo to je asi pravda, to jsem zas ulítnul na pitomosti, co mi nedošla :-) ale kdybys kouknul na ten Twitter, tak tam ty data vůbec přes AJAX znovu nevyžadují. Nevím odkud je berou, ukládají to jinam. Co jsem koukal, mají tam nějaký iframe, ale konkrétní data uživatele jsem v něm taky nenašel.
Witiko
Profil
joe:
Je dost možné, že ukládají a přenáší pouze metadata kontaktu, která rovnou na straně klienta jen zasazují do šablony. Pokud však přenášíš stránku se vším všudy, je cache tvůj nejlepší přítel. Není důvod mít ta data uložena dvakrát (jednou někde na stránce ve skrytém elementu, podruhé v cache).
joe
Profil
Witiko:
Tak jsem se konečně dostal k tomu, abych se na to trochu podíval (HTML 5 History), sice to "funguje", ale nějak zvláštně.

Co jsem dobře pochopil a díval se na různé weby, kde už to mají využité, tak je potřeba uložit inicializační stav, ale podle mě jen na stránce, kde se bude History.pushState používat, že jo? Využil jsem tedy History.replaceState().

Při úspěšném AJAX požadavku znovu uložím stav do historie (pushState) a při události onpopstate zpracuju ten aktuální stav. Zdá se, že všechno funguje. Ale pokud nastavuju inicializační stav jen někde, tak při pohybu šipkama <- a -> v prohlížeči se dostanu někdy na stránku, kde vidím jen vrácenou odpověď v JSON.

Pokud inicializační stav nastavuju na každé stránce, pohybování v prohlížeči (zpět/vpřed) funguje, ale na těch stránkách, kde nepotřebuju ukládat ty stavy ukládat také dochází ke zpracování (tzn. zbytečný AJAXový požadavek) v události onpopstate.

Je to pochopitelné? Dal bych příklad, ale zatím nemám projekt nikde nevřejně nahraný, až do udělám, napíšu i sem. Ale kdyby někdo věděl co s tím a nebo mi ukázal nějakou ukázku stránky, kde to funguje tak jak by mělo....
_es
Profil
Witiko:
onhashchange = function() {
if(!location.hash.length) alert("prvni!");
};
Radšej by som vlastnosti objektu window vždy priradzoval spôsobom:
window.vlastnosť = hodnota;
Niektoré prehliadače majú tendenciu niekedy vytvoriť akúsi zvláštnu globálnu premennú, ktorá svojim názvom prekryje pôvodnú vlastnosť, viď tu (prvý príklad).

joe:
Niečo sa už riešilo tu a tu, možno by sa to zišlo vylepšiť.
joe
Profil
_es:
Myslím, že píšeš o něčem trochu jiném, než jsem měl na mysli (nemám problém s tím, abych znovu načetl to, co mám). Špatně se mi to popisovalo, ale prozatím (než bude veřejný můj web) jsem našel i jiný web, s naprosto stejným problémem.

Ještě napíšu, že tenhle problém se děje jenom v Chrome, to jsem nějak zapomněl napsat.


stránka, kliknout na jakoukoli ikonku pod nadpisem (provede se AJAX), kliknout na logo (zde bez AJAXu) a teď dvakrát stisknout v prohlížeči tlačítko zpět (dvakrát proto, protože on tam při každém načtení volá pushState - tzn. má aktuálně načtenou stránku v historii vždy dvakrát, to pro teď není podstatné). Nezobrazí se stránka, ale dojde k výpisu JSON dat. a dál ovládání zpět nefunguje.

Objeví se varování - "Resource interpreted as Document but transferred with MIME type application/json."


Pravděpodobně to bude bug v Chrome (Opera a Firefox fungují), něco už jsem na zmíněné varování našel, ale myslím že to nesouviselo přímo s tímhle problémem. Ale bylo by dobré to nějak opravit (pokud to půjde - přímo v JS)

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

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

0