Autor Zpráva
Martin Adámek
Profil
Na webu s ajaxovou změnou obsahu pravého sidebaru mi zlobí ajax.

V pravém sidebaru se seznamem videí je formulář,
v něm select s rubrikami,
a na něm událost onchange, která při změně výběru spustí JS,
který odešle požadavek na server s novým parametrem (zvolenou rubrikou):
httpRequest = new XMLHttpRequest();
httpRequest.open("GET", url, true);

A výsledek nechá zobrazit jako nový obsah pravého baru:
httpRequest.onreadystatechange= function () {document.getElementById("pravybar").innerHTML = httpRequest.responseText;} 


Jenže to vše funguje jen v prohlížeči, ve kterém se ten web nedávno používal.
Při první návštěvě toho webu v prohlížeči (IE, Chrome, asi i FF) to nejde.
Uživatel musí kliknout na odkaz "přehrát vše", "přehrát aktuální" nebo na některé z nejsledovanějších videí dole. Když cokoliv z toho udělá, tak to potom šlape, jak má, i další dny. Zase až do nějaké několikadenní pauzy, kdy ten prohlížeč ten web nenavštíví.
Sušenky nepoužívám. Občas se tam jedna objeví (asi jiná aplikace na stejném serveru), ale její odstranění nemá na fci vliv.

Zkoušel jsem pomocí JS alertů, vypisování timestampu do html a logováním do txt souboru sledovat, co se ještě udělá, a co už ne:
-obslužný JS zavěšený na onchange se spustí
-php spuštěné tím javascriptem se spustí, proběhne celé až do konce, nevyvolá chybu
- "httpRequest.onreadystatechange= " se spustí, ale nedoběhne do konce (!)
- tzn. alert umístěný před "document.getElementById("pravybar").innerHTML =..." vyskočí, ale alert umístěný za ním nevyskočí
- zkusil jsem těsně před tu změnu innerHTML dát příkaz >> document.getElementById("pravybar").style.background="blue"; <<, a ten úspěšně proběhl, takže >>document.getElementById("pravybar")<< funguje, prohlížeč se k tomu elementu dostane
- přitom ale z logu vidím, že vyvolávaný php skript doběhne úspěšně až do konce
- proto nechápu, proč >>document.getElementById("pravybar").innerHTML = httpRequest.responseText;<< neproběhne ?
- je to kam dát, je tam snad i co dát, a stejně se to tam nedá, a ještě javascript nedoběhne do konce

Přitom stačí, aby uživatel aktivoval odkaz přehrát vše/aktuální/nejsledovanějšívideo, a pak to vše funguje, dokud nenastane několikadenní pauza v tom prohlížeči. Ruční vymazání cache prohlížeče ani cookies na to vliv nemá. Zkoumal jsem, jaké proměnné (get parametry) tomu ajax.php posílám při jeho prvním zobrazení z index.php přes file_get_contents , a jaké potom z JS, a žádný rozdíl jsem v tom nenašel.

Nemám nějakou chybu v tom obslužném javascriptu? Nebo čím to může být?
Obslužný JS zní:
function pravybar(url)
{
  //alert('pravybar url:'+url);
  
        if (window.ActiveXObject)
        {
          httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        }
        else
        {
          httpRequest = new XMLHttpRequest();
        }
        httpRequest.open("GET", url, true);
        httpRequest.onreadystatechange= function () {/*document.getElementById("pravybar").style.background="blue";*/ document.getElementById("pravybar").innerHTML = httpRequest.responseText; vyskaokna(); /*alert('onr2');*/} ;
        httpRequest.send(null);
        
        return true;
}


díky.
ShiraNai7
Profil
Martin Adámek:
Uncaught TypeError: Cannot read property 'style' of null okna.js:25
vyskaokna okna.js:25
httpRequest.onreadystatechange

To znamená, že tohle:
document.getElementById('seznam')
.. vrací null. Element s ID seznam v době provádění toho skriptu neexistuje.
Martin Adámek
Profil
ShiraNai7:
To je bohužel důsledek toho problému, ne příčina.
Normálně (když .innerhtml=... proběhne) tenhle druhej skript (vyskaokna() v okna.js) upravuje max-height seznamu podle výšky okna.
Ta chyba se vyskytovala už předtím, než jsem tenhle druhej skript na úpravu výšky seznamu vůbec vytvořil.

Mmch, kde čteš tenhle pěknej popis chyby? Obecně se mi může hodit...
Na ladění JS mám jen toolbar Webdeveloper, ale ten mám jen ve svým prohlížeči, ve kterým se mi ta chyba nevyskytuje.
Chamurappi
Profil
Reaguji na Martina Adámka:
Při první události httpRequest.onreadystatechange ještě nemusí být načtená data. Měl bys kontrolovat httpRequest.readyState a pokud v něm není čtyřka, nedělat nic.
Martin Adámek
Profil
Chamurappi:

Zkusil jsem teda přidat tuhle podmínku
        httpRequest.onreadystatechange= function () 
          { 
            if (httpRequest.readyState==4)
              {
                document.getElementById("pravybar").innerHTML = httpRequest.responseText; 
                vyskaokna();
              } 

          } ;
(vycházeje z toho, že se předtím ta fce spouštěla i opakovaně, takže by se to nejdřív ignorovalo (a nehodilo chybu) a příště už úspěšně vykonalo)

ale chová se to pořád stejně.

Nebo má JS něco jako "počkej dokud" (to by asi šlo nějakým do-while, resp. repeat-until cyklem, i když by to asi byla dost nečistá zbytečná zátěž),
nebo jak to mám přesně použít?
_es
Profil
Martin Adámek:
Nenastáva na webe viac AJAXových dotazov rýchlo za sebou? Viď: Časté potíže, zajímavosti a poučné debaty » Používejte var. Definuj httpRequest ako premennú funkcie pravybar. Prečo nazývaš funkciu rovnako ako id nejakého elementu? Síce to asi nerobí v tomto prípade problémy, no nie je to dobrý nápad.
Martin Adámek
Profil
_es:
jj, zdá se, že se ta fce. spouští víckrát po sobě.

V JS jsem vždycky dělal jen drobnosti, a ani jsem nevěděl, že v něm můžu použít "var", v příkladech se moc nevyskytuje
(v php mi deklarace proměnných chybí tak moc, až jsem v její existenci v JS ani nedoufal...)

Doplnil jsem teda deklaraci proměnné httprequest - zkoušel jsem ji nejdřív jednou centrálně, jen "var httprequest;" ,
i potom samostatně v podmínkách (např. "var httpRequest = new XMLHttpRequest();"), aby se hned ve varu vědělo, jaký to je typ,
ale nepomohlo mi ani jedno, chová se to stejně.

Zkoušel jsem přidat var i ke vstupnímu parametru, ale tam evidentně nepatří, skript se pak vůbec nevykonával a webdeveloper házel chybu.

Fci jsem dal stejný název jako id elementu, jehož obsah ta fce mění, pač mi to přišlo logický (podobně jako když přenášíš obsah php proměnné getem nebo postem v parametru stejného názvu jako má ta proměnná), ale teď jsem teda fci. přejmenoval.

Přidání varu ani přejmenování fce nepomohlo, chová se to pořád stejně.
Nějaký další nápad, co by tomu mohlo být?
_es
Profil
Martin Adámek:
Príkaz var nemá byť v podmienenom príkaze, viď toto vlákno. Pre objekt XMLHttpRequest použi najprv nastavenie vlastnosti onreadystatechange až potom metódu open. V kóde máš všade return !pravybarjs(... čím rušíš východziu akciu (funkcia vracia true) - aký to má zmysel pre <select>? Kombinácia udalostí onchange a onblur v ňom vyzerá pochybne. Pozrel si si vôbec, čo sa pokúšaš cez AJAX stiahnuť? Elementy <script> pridané cez innerHTML sú nefunkčné.
Martin Adámek
Profil
_es:
Tak jsem opravil var a odstranil "!return"
(to tam bylo ze setrvačnosti po zkopírování syntaxe z onclicku u JS otvírání odkazu do nového okna)
a už to funguje. Ale jestli dobře chápu, tak (hlavní) příčina byla (a pořád je) úplně jinde.
Ale i tak díky za uvedení kódu do čistší podoby a utřídění povědomí o syntaxi JS.
(to onblur tam mám proto, že přistisku Ctrl+R se natahuje jiný obsah, než odpovídá volbě v selectu, a to onblur je cesta, jak tam dostat aktuální obsah bez nutnosti měnit hodnotu selectu na jinou položku a zase zpátky (zkoušel jsem onload, ale to se nějak nevykonávalo)
)

A pro případ, že by se někomu dělo něco podobnýho...


Řešení - proč se to dělo

Z nastavení htaccessu na hostingu u svého soukromého webu jsem zvyklý na to, že subdoménu "www." uživatel do url nemusí zadávat. Když napíšu do adresního řádku "adamek.cz*", samo mě to přesměruje na "www.adamek.cz*".
Takže "www." nezadávám, ale u "svých" webů mám pocit, jako by se stalo, a doleva před doménu moc nekoukám...

Tady je stejná věc řešená trochu jinak, a doplňování subdomény nefunguje pro testovací verzi webu.
Celou dobu šlo patrně o to, že když jsem zadal "nachodska.tv/tv-2" bez subdomény "www.", tak ajax nešel (vysvětluju si to jako ochranu proti JS podstrčení obsahu z jiného serveru - ostatně ani přes htaccess nejde podstrkávat z jiné (sub)domény, nebo aspoň já to neumím).
Ponaučení tedy zní: "Zlobí-li vám ajaxové podstrkování obsahu přes innerhtml, podívejte se pořádně, na jaké jste (sub)doméně a jestli tedy jako návštěvník máte v prohlížeči v adresním řádku stejnou (sub)doménu, z jaké ajaxem doplňujete obsah elementu."

Člověk by si rval zbytky vlasů, že si nevšim takový základní věci, ale ony dnes prohlížeče celou adresu kromě prvních domény házejí do šeda, a navíc nové verze začaly schovávat protokol (ale při kopírování do schránky ho tam dají), tak kdo si má všimnout, že mu chybí subdoména, a hlavně kdo tomu má věnovat pozornost když ví, že nevadí "chybějící" protokol, že...

Odpovídá tomu i symptom "Jenže to vše funguje jen v prohlížeči, ve kterém se ten web nedávno používal."
- zřejmě jsem v adresním řádku napsal dvě písmena, dal šipku dolů, enter, a subdoména tam byla.

Souhlasí i druhý symptom "Přitom stačí, aby uživatel aktivoval odkaz přehrát vše/aktuální/nejsledovanějšívideo, a pak to vše funguje,"
- u těch odkazů jsem dynamicky tvořil cílové URL jako absolutní, tedy i se subdoménou "www." .


Budu rád, když ostatní zkontrolujete, jestli ten závěr na vašich počítačích souhlasí, ale kontroloval jsem to teď v práci na 4 počítačích, v každém 3 prohlížeče, a zdá se, že to je ono.
Každopádně díky za spolupráci, aspoň mám vyladěný kód a předešlo se i dalším možným chybám.
_es
Profil
Martin Adámek:
když jsem zadal "nachodska.tv/tv-2" bez subdomény "www.", tak ajax nešel
Do metódy open sa dá zadať aj relatívne URL, alebo jednotlivé časti adresy stránky získať z objektu location.

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:

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

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