Jak detekovat zapnuty JavaScript pomoci PHP?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Endrju
Člen | 147
+
0
-

Zdravim!

Ne jednou jsem tuhle otazku uz resil a nyni ji v Nette resim take.

Znate nejaky dobry zpusob jak pomoci Nette (PHP) detekovat, zda ma uzivatel zapnuty JavaScript?

Ja jedno reseni nasel, ale zjistuji, ze to ma sve mouchy (ty nastinim pozdeji).

Jak to resit obecne?

  • do stranky si napsat presmerovani pomoci JS na nejaky PHP script, ktery kdyz se spusti, tak nastavi nejakou promnou, pokdle ktere pozname, ze je JS zapnuty
  • kdyz promenna nastavena nebude, je jasne, ze nedoslo k JS presmerovani a JS je tim padem vypnuty.

Zkousel jsem to resit ve sve modularni aplikaci, ale narazil jsem na problem (popisu pozdeji). Aktivnost JS potrebuji detekovat pouze v administracni casti. Ta je zabezpecena autorizaci uzivatele.

Postup:

  1. zadam na prihlasovaci strance udaje pro vstup do admin casti
  2. po presmerovani se zobrazi hlavni stranka admin modulu, ktera ma spolecny layout pro vsechny stranky admin modulu.
  3. v tomto layoutu je vsak nasledujici kod, ktery me (pri zapnutem JS) presmeruje na presenter JsDetection a akci jsIsRunning:
...
{if $javaScriptDetection['isRunning'] == FALSE}
<script type="text/javascript">
<!--
	window.location = "JsDetection/jsIsRunning";
//-->
</script>
{/if}
...
  1. toto presmerovani se provede pouze pokud je v session nastavena hodnota isRunning na FALSE, kterou prednastavuji v BasePresenteru jeste pred vykreslovanim layoutu stranky.
...
protected function beforeRender()
{
	...
	$session = Environment::getSession('javaScriptDetection');
	if (!isset($session->javaScriptDetection['isRunning'])) {
		$session->javaScriptDetection['isRunning'] = FALSE;
	}
	$this->template->javaScriptDetection = $session->javaScriptDetection;
	...
}
...
  1. pokud je JavaScript zapnuty, tak jsem presmerovan na presenter JsDetection a akci jsIsRunningm ve ktere prenastavim v session hodnotu isRunning na TRUE a po te presmeruji na presenter News (tedy na tentyz presenter, na ktery jsem byl presmerovan po prihlaseni)
public function actionJsIsRunning()
{
	$session = Environment::getSession('javaScriptDetection');
	$session->javaScriptDetection['isRunning'] = TRUE;

	// presmerovani na hlavni stranku
	$this->redirect('News:');
}
  1. Nyni uz vim, zda ma uzivatel JavaScript zapnuty ci vypnuty a tuto informaci mam ulozenou v session.
  2. z podminky, ktera obaluje JS presmerovani v bodu 3) je nyni jasne, ze pokud jsme uz jednou v session nastavili hodnotu isRunning na TRUE (v akci – krok 5), tak k tomuto presmerovani znovu nedojde. Neni to potreba – vime, ze uzivatel ma JS zapnuty. Pokud je hodnota nastavena na FALSE, tak to znamena, ze k presmerovani jeste nedoslo a tedy se o nej budeme pokouset pri kazdem naccteni layoutu.

A ted ke slibenemu problemu, ktery nevim jak vyresit a doufam, ze mi nejak pomuzete :).

Kdyz behem prace v admin casti vyprsi session, tak jsem pri dalsi akci presmerovan na login s tim, ze se ulozi backlink. Po opetovnem prihlaseni me aplikace chce vratit zpet na presenter a akci, kde jsem byl naposledy. Jenze v layoutu mam ono presmerovani, takze pokud jsem mel rozpracovano napr. URL http://.../.../document_root/diskuze/edit/1, tak po opetovnem prihlaseni a oziveni posledni provadene operace se stane, ze se bude znova zjistovat, zda ma uzivatel zapnuty JS (vyprsela session, tedy i tato informace se ztratila). Tedy se bude znova presmerovavat a vznikne z toho napr. takovato URL http://.../.../document_root/diskuze/edit/JsDetection/jsIsRunning a vse na tom zkrachuje.

Jak tohle vyresit a opravit? Kdyz bude stav aplikace ozivovan po vyprseni session, tak potrebuju zjistit, zda ma uzivatel zapnuty, ci vypnuty JS a nastavit tak promennou v session, ale potom potrebuji presmerovat na uzivatelovu rozpracovanou praci (tedy do stavu nez session vyprsela).

Nemam jeste dostatecne znalosti na to, abych tyhle veci s ozivenim stavu aplikace po presmerovani a za takove situace vyresil sam. Proto bych byl moc vdecny, kdyby jste nekdo nabidli nejake reseni. Predem moc dekuji!

22
Člen | 1478
+
0
-
  • jak může vypršet session v admin části? co prodloužit session?
  • co <noscript>?
  • co cookies?
mkoubik
Člen | 728
+
0
-

Co použít {$baseUri}?

...
{if $javaScriptDetection['isRunning'] == FALSE}
<script type="text/javascript">
<!--
	window.location = "{$baseUri}JsDetection/jsIsRunning";
//-->
</script>
{/if}
...
Endrju
Člen | 147
+
0
-

22 napsal(a):

  • jak může vypršet session v admin části? co prodloužit session?
  • co <noscript>?
  • co cookies?
  • napr. dlouha neauktivita. Nebo delas v admin casti, otevres si firebug, refreshnes a razem te to hodi na prihlaseni.
  • jak tomu pomuze noscript? Muzu tam napsat akorat nejake HTML, kde reknu „Mate vypnuty JS“. Kdyz mezi tagy <noscript> napisu nejaky PHP kod, zpracuje se i kdyz je JS zapnuty. Napr:
{assign $script 'script'}
<noscript>
	{assign $script 'no script'}
	<p>Máte vypnutý JavaScript.</p>
</noscript>
{$script}

Vzdy se vypise „no script“ (proemnna $script se prepise vzdycky, i kdyz mam JS zapnuty) a <p>Máte vypnutý JavaScript.</p> se vypise jen kdyz je vypnuty JS.

  • s problemem jaky mam tusim cookies nijak nepomuzou. Porad potrebuju vyresit oziveni aplikace a po presmerovani JavaScriptem

Diky za navrhy

Editoval Endrju (8. 4. 2010 13:26)

Endrju
Člen | 147
+
0
-

mkoubik napsal(a):

Co použít {$baseUri}?

...
{if $javaScriptDetection['isRunning'] == FALSE}
<script type="text/javascript">
<!--
	window.location = "{$baseUri}JsDetection/jsIsRunning";
//-->
</script>
{/if}
...

musel bych zadat bud kompletni URL vcetne http:// jinak se string, ktery predavam funkci windows.location pripoji ke stavajici URL. Mohl bych nejakym zpusobem zjistit a sestavit celou URL od Http:// az po cast /admin/ za kterou bych pripojil „JsDetection/jsIsRunning“. Co pak ale s ozivenim stavu aplikace po prihlaseni? Jak modifikovat kod v bodu 5) aby po zpracovani presmeroval na uzivatelovu puvodni url, ktera je v backlinku? Dival jsem se jak to je udelano u loginu: $this->getApplication()->restoreRequest($this->backlink); zkusil jsem tohle dat pred presmerovani. TO melo ale za nasledek, ze se aplikace zacyklika.

Ondřej Mirtes
Člen | 1536
+
0
-

„You're asking the wrong question“ – PHPčko nějaký Javascript nemá vůbec zajímat, k čemu to konkrétně potřebuješ? (To je jako kdyby PHPčko mělo zajímat, jaké rozlišení monitoru uživatel používá.)

Endrju
Člen | 147
+
0
-

uz jsem problem vyresil i s ozivenim requestu. Ted musim bezet, pak editnu postu a vysvetlim Ondro.

EDIT:

Ondřej Mirtes napsal(a):

„You're asking the wrong question“ – PHPčko nějaký Javascript nemá vůbec zajímat, k čemu to konkrétně potřebuješ? (To je jako kdyby PHPčko mělo zajímat, jaké rozlišení monitoru uživatel používá.)

K tomu vysvetelni proc vubec neco takoveho chci: Predstav si, ze delas system, ktery budou obsluhovat i starsi lidi, kteri umi jakz takz pouzivat MS Word, ale uz vubec nic nevi o programovani a ze web stranka ma nejake tagy. K editovani prispevku pouzivam CKEditor, ktery formatuje text pomoci HTML. Kdyz uzivatel bude chtit editovat prispevek a stane se, ze ma uzivatel vypnuty JavaScript nebo jej prohlizec nepodporuje, tak se mu misto CKEditoru zobrazi prosta TextArea a v ni spousty HTML tagu. Nejaky starsi pan by vubec nechapal co za Matrix na nej byl spachan. Proto jsem potreboval zjistit pomoci PHP, zda ma uzivatel zapnuty JS a v pripade ze nema, tak PHP funkcemi odstranim HTML tagy atd, aby zbyl jen holy text, se kterym si starsi uzivatel uz poradi.

A ted jak jsem to vyresil (uvedu jen zmeny v bodech z prvniho prispevku):

  1. zamenen JS kod na:
{if $javaScriptDetection['isRunning'] == FALSE}
<script type="text/javascript">
<!--
	{assign $backlink $presenter->getApplication()->storeRequest()}
	window.location = "http://" + location.host + {$baseUri} + "admin/JsDetection/jsIsRunning/" + {$backlink};
//-->
</script>
{/if}
  1. metoda upravena a zmenen nazev metody, pridan paramert obsahujici $backlink
/**
* Ulozi do session, ze ma uzivatel JavaScript zapnuty
*
* @param $id backlink
*/
public function actionJsIsRunning($id = '')
{
	$session = Environment::getSession('javaScriptDetection');
	$session->javaScriptDetection['isRunning'] = TRUE;

	// presmerovani na hlavni stranku
	$this->getApplication()->restoreRequest($id);
	$this->redirect('News:');
}

Ve vysledku tedy pokud by byla session smazana nebo vyprsela (ci co ja vim), tak bude uzivatel presmerovan na login. Po presmerovani by byl presmerovan zpet na posledni URL podle toho co je v backlinku. To by se stalo, kdybych tam nemel JavaScript presmerovani. To kdyz se provedlo, ztratil se backlink. Ten tedy predam jako parametr akci na kterou pomoci JS presmeruju. V te akci pak ulozim do session, ze je JS zapnuty a presmeruju podle backlinu jak bylo puvodne zamysleno.

PS: mozna to vysvetluju trochu krkolome, ale to je tim, ze Nette jeste tak dobre neznam.

Editoval Endrju (8. 4. 2010 21:14)

Mortaelth
Člen | 24
+
0
-

No a proc se vubec nekam presmerovavat? Proc nepouzit AJAX?

Endrju
Člen | 147
+
0
-

Mortaelth napsal(a):

No a proc se vubec nekam presmerovavat? Proc nepouzit AJAX?

Pokud nahodis funkcni reseni tak sem s nim ;). Budu jedine vdecny.

Btw.: ajax se mi nepovedlo rozchodit jeste v zadne aplikaci :/. Chystam se to odzkouset na skeletonu a zkusit prijit na to v cem delam chyby.

PS: editoval jsem svuj post c.7

Editoval Endrju (8. 4. 2010 21:14)

Ola
Člen | 385
+
0
-

Aplikace by měla běžet i bez JS, zjišťovat v PHP jestli je zapnutý JS je .. .. .. špatné.

Endrju
Člen | 147
+
0
-

Ola: proc jsem tohel resil je postu #7 na zacatku. Aplikace bezi i bez JS. Ale okud jsem se rozhodnul pouzivat zmineny JavaScriptovy editor, tak jak jinak bys vyresil, aby se pri vypnutem JS zobrazil v text-area text bez HTML znacek?

Mikulas Dite
Člen | 756
+
0
-

Bylo by mnohem lepší mít nějakou zprávu pro uživatele JS je vypnutý, zapni to v noscript, případně dokonce úplně mezi vším ostatním html a pomocí js jí schovat. Je to rychlejší (žádný další redirect), čistší a neplete se do toho php.

marek.dusek
Člen | 99
+
0
-

Sice nevim, jak si pomuzes, kdyz „starsimu uzivateli s vypnutym javascriptem“ (existuje takovy?) nabidnes verzi textu se stripnutymi tagy (jak se to pak ulozi, resp. zobrazi? Proste neformatovany text?), ale kdyz uz to tedy resit, co pouzit obraceny postup, kdy:

  1. vytvoris textareu s „cistym“ textem, ktera bude normalne videt
  2. vytvoris stejne tak textareu, ktera se ma promenit v js editor, ale das ji „display: none“ a „disabled“
  3. pridas javascript, ktery tu prvni skryje a disabluje (resp. zmeni atribut name, cokoli) a naopak tu druhou zobrazi

Takze pokud ma uzivatle Js zapnuty, prosty text nevidi a neodesila, vidi jen editor, naopak pokud ho ma vypnuty, vidi jen prosty text.

Endrju
Člen | 147
+
0
-

Mikulas Dite napsal(a):

Bylo by mnohem lepší mít nějakou zprávu pro uživatele JS je vypnutý, zapni to v noscript, případně dokonce úplně mezi vším ostatním html a pomocí js jí schovat. Je to rychlejší (žádný další redirect), čistší a neplete se do toho php.

Tag <noscript> pouzivam prave k upozorneni, ze ma uzivatel JS vypnuty a ze funkcnost nekterych veci bude omezena. A se schovanim klasicke TextArey pomoci JS – hm.. mam nasazeneho brouka do hlavy :). To je dost dobry napad (bez redirectu :)).


marek.dusek napsal(a):

Sice nevim, jak si pomuzes, kdyz „starsimu uzivateli s vypnutym javascriptem“ (existuje takovy?) nabidnes verzi textu se stripnutymi tagy (jak se to pak ulozi, resp. zobrazi? Proste neformatovany text?)

Spise se zeptej – neexistuje takovy :)? Rekneme, ze resim i tyhle detaily…
Ano, stripnu tagy, zbytecne mezery a odradkovani, kterych je vice nez 2 za sebou atd.. A pak to ulozim do DB se signaturou ze JS je vypnuty. Kdyz to pak zobrazim, tak to vypisu jako {!=nl2br($content)} jinak vypisuju bez funkce nl2br().

ale kdyz uz to tedy resit, co pouzit obraceny postup, kdy:

  1. vytvoris textareu s „cistym“ textem, ktera bude normalne videt
  2. vytvoris stejne tak textareu, ktera se ma promenit v js editor, ale das ji „display: none“ a „disabled“
  3. pridas javascript, ktery tu prvni skryje a disabluje (resp. zmeni atribut name, cokoli) a naopak tu druhou zobrazi

Takze pokud ma uzivatle Js zapnuty, prosty text nevidi a neodesila, vidi jen editor, naopak pokud ho ma vypnuty, vidi jen prosty text.

Taky zajimavy napad! Koukam, ze nad tim budu muset jeste podumat :). Neznam, ale moc kyzene JS funkce, ktere by bylo treba pouzit a obecne JS moc nepisu.. Nepodelite se o nejakou ukazku s kodem :)?

Editoval Endrju (8. 4. 2010 23:37)

marek.dusek
Člen | 99
+
0
-

to je trivialni, neco jako

<textarea id='ta-cista' name='text-clanku'> ... </textarea>

<textarea id='ta-editor' style='display: none' disabled='disabled'> ... </textarea>
<script>
var taPlain = document.getElementById('ta-cista');
var taEditor = document.getElementById('ta-editor');
var name = taPlain.name;

taPlain.style.display = 'none';
taPlain.name = null;
taPlain.disabled = true;

taEditor.style.display = 'block';
taEditor.name = name;
taEditor.disabled = false;
</script>

idea je snad jasna ;)

Honza Kuchař
Člen | 1662
+
0
-

No jasny, ale jak to uložit. Já bych udělal akorát skrytou textareu (kde za normálních okolností bude editor)

<textarea id='ta-editor' name="bla" style="display: none;"> ... </textarea>
<div id="hlaska">Používáte nekompatibilní prohlížeč. Editace článku není možná.</div>
// jQuery
$("#obal").show();
$("#hlaska").hide();

Kdyz mezi tagy <noscript> napisu nejaky PHP kod, zpracuje se i kdyz je JS zapnuty.

Zdá se, že zde nastává chyba. Zjisti si, jak probíhá komunikace s webovým serverem a jak funguje prohlížeč (a vůbec co to je). Bez této základní znalosti budeš narážet co chvíli. To co jsi totiž napsal, bys nikdy nenapsal, kdyby jsi věděl, jak to funguje. :) Je to totiž nonsense.

marek.dusek
Člen | 99
+
0
-

„No jasny, ale jak to uložit.“

<input type='hidden' id='js-zapnuty' name='js-zapnuty' value='0' />
<script>
document.getElementById('js-zapnuty').value = 1;
</script>

?

Endrju
Člen | 147
+
0
-

honzakuchar napsal(a):

Kdyz mezi tagy <noscript> napisu nejaky PHP kod, zpracuje se i kdyz je JS zapnuty.

Zdá se, že zde nastává chyba. Zjisti si, jak probíhá komunikace s webovým serverem a jak funguje prohlížeč (a vůbec co to je). Bez této základní znalosti budeš narážet co chvíli. To co jsi totiž napsal, bys nikdy nenapsal, kdyby jsi věděl, jak to funguje. :) Je to totiž nonsense.

Ty jo, me snad omyjou.. :). Jak me muzes narknout z neceho takoveho :D? Byla to jen reakce na jeden z prvnich prispevku a samozrejme vim, ze to proste nikdy nemuze fungovat a vubec me nenapadlo, ze me tu nekdo bude „napadat“ za to, jak jsem to napsal a podezrivat z toho, ze pri tvorbe PHP aplikaci snad takove veci nevim :/. Tsss.

Jinak moc pekne napady tady!

_Martin_
Generous Backer | 679
+
0
-

Nevyresilo by generovat ten odkaz pres makro link?

Ondřej Mirtes
Člen | 1536
+
0
-

Podle mě je to šílenost a uživateli s vypnutým JS bych zobrazil obyčejnou textareu s HTML kódem. Řešit nějaké přeformátovávání z toho plaintextu a kompatibilitu… brrr…

Elegantní řešení je asi jedině Texy :)