Autor Zpráva
Fisir
Profil
Ahoj,
vytvářím skript, který zjistí titulek všech stránek na mém webu (projede odkazy na stránce a ignoruje ty, co v sobě mají http://). Cyklem se dotazuje mého serveru, který mu titulek v prostém textu vrátí. Když však JavaScriptový kód spustím, vyhodí to: TypeError: Cannot read property '7' of undefined

function getTitles(){
    var tag = "a";
    var pole = document.getElementsByTagName(tag);
     for(i = 0; i < pole.length; i++) {
          if(pole[i].href.search(/http:\/\//) == -1 && pole[i].href.search(/javascript:/) == -1){
              if(pole[i].title == "" || !pole[i].title){
                      var xmlhttp,titulek;
                    if (window.XMLHttpRequest){
                        xmlhttp=new XMLHttpRequest();
                    } else {
                        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
                    };
                    xmlhttp.onreadystatechange=function(){
                        if(xmlhttp.readyState==4 && xmlhttp.status==200){
                            titulek = xmlhttp.responseText;
                            pole[i].title = titulek;
                        };
                    };
                    xmlhttp.open("GET",".href,true]http://www.j-jaburek.tk/etc/title.php?url=".pole[i].href,true);
                    xmlhttp.send();
              };
          };
    };
};
Napadlo mě, zda to nekoliduje s vyznačením externích odkazů, ale nevím, proč by mělo. Živá ukázka — www.j-jaburek.tk/o-webu
Darker
Profil
xmlhttp.open("GET",".href,true]http://www.j-jaburek.tk/etc/title.php?url=".pole[i].href,true);
Tady tenhle řádek vypadá dost divně. Pokud nemáš nějaký spešl prototype pro string (a podle mojí konzole asi ne) nemá cenu u něj hledat vlastnost pole.


Proč to hledáš cyklem? Proč radši z titulek.php nenačteš titulky všech HTML dokumentů? Nebo, alespoň, proč si nejdřív nenačteš všechny HTML odkazy a pak nezjistíš všechny titulky najednou? Tohle je fakt trochu prasárna...
    var tag = "a";  //Mám za to, že tohle je zbytečnost.
    var pole = document.getElementsByTagName(tag);
Fisir
Profil
Reaguji na Darkera [#2]:
Tady tenhle řádek vypadá dost divně.
První označený úsek zmršila diskuse. To druhé, to je jasně špatně, takhle se spojují řetězce v PHP.

Proč radši z titulek.php nenačteš titulky všech HTML dokumentů?
To by nebylo ohleduplné vůči množství odkazů na jedné stránce.

Domů se dostanu až za týden, takže to vyzkouším později (jsem bez notebooku na táboře).
Darker
Profil
Fisir:
To by nebylo ohleduplné vůči množství odkazů na jedné stránce.
A stahovat je postupně je ohleduplnějčí čím? Jde mi o to, abys nevytvářel tolik požadavků a titulky stáhl v jedné dávce.
Fisir
Profil
Nyní mám tento kód:
function getTitles(){
    var pole = document.getElementById("pageContent").getElementsByTagName("a");
    var links = "";
     for(i = 0; i < pole.length; i++) {
        if(
        pole[i].href.search(/j-jaburek.tk/) != -1 && 
        pole[i].href.search(/javascript:/) == -1 &&
        pole[i].href.search(/mailto:/) == -1
        ){
            if(pole[i].title == "" || !pole[i].title){
                      var xmlhttp,titulek;
                    if (window.XMLHttpRequest){
                        xmlhttp=new XMLHttpRequest();
                    } else {
                        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
                    };
                    xmlhttp.onreadystatechange=function(){
                        if(xmlhttp.readyState==4 && xmlhttp.status==200){
                            if(xmlhttp.responseText != "" || xmlhttp.responseText != "Externí weby nejsou podporovány!"){
                                pole[i].title = xmlhttp.responseText;
                            };
                        };
                    };
                    xmlhttp.open("GET",".href,true]http://www.j-jaburek.tk/etc/title.php?url="+pole[i].href,true);
                    xmlhttp.send();
              };
        };
    };
};

Nechápu ovšem, proč nefunguje: Uncaught TypeError: Cannot set property 'title' of undefined (řádek 20). První označený úsek je problémový řádek, druhý je chyba diskuse.
Keeehi
Profil
Protože je to v anonymní funkci. Pokud 2. řádek vyhodíš vně funkce getTitles(), měla by být proměnná pole viditelná globálně a pak i v té anonymní funkci.
Fisir
Profil
Reaguji na Keeehiho [#6]:
Hodil jsem řádek var pole = document.getElementById("pageContent").getElementsByTagName("a"); před function getTitles(){. Ukazuje to více chyb:
Uncaught TypeError: Cannot call method 'getElementsByTagName' of null        ja.js:40
Uncaught TypeError: Cannot read property 'length' of undefined               ja.js:43
Keeehi
Profil
1. chyba souvisí s tím, že v době volání getElementById("pageContent") ještě element s id="pageContent" neexistuje. Tento javascript přesuňte až za ten element. Jistota je těsně před </body>
2. chyba souvisí s tou první a až tu první vyřešíte, 2. zmizne sama.
Fisir
Profil
Reaguji na Keeehiho [#8]:
Teď se ukazuje ta samá chyba jako v [#5].
Keeehi
Profil
Prosím o odkaz na živou ukázku.
Fisir
Profil
Reaguji na Keeehiho [#10]:
Je stále stejný jako v [#1] — www.j-jaburek.tk/o-webu
Keeehi
Profil
Fisir:
Je stále stejný
Omlouvám se, to jsem přehlédl.

Zapomněl jsem, že také i není vidět v té anonymní funkci. Tím se to trochu komplikuje.

Ajaxový požadavek musí vypadat takto: xmlhttp.open("GET","http://www.j-jaburek.tk/etc/title.php?url="+pole[i].href+"&i="+i);

A odpověď takto: {"i":"5","title":"titulek"} - to číslo za i je jen zkopírované to, co se posílá v tom požadavku.

if(xmlhttp.responseText != "" || xmlhttp.responseText != "Externí weby nejsou podporovány!"){
    var odpoved = JSON.parse( xmlhttp.responseText );
    pole[odpoved.i].title =odpoved.title;
};
Fisir
Profil
Reaguji na Keeehiho [#12]:
Vypadá to, že to stále nefunguje. A vůbec, jakto, že tam není vidět, když je deklarována (stejně jako pole) před tímto cyklem?
var odpoved = JSON.parse( xmlhttpt.responseText );
Máš tam přebytečné písmeno.
Keeehi
Profil
i není vidět, protože je deklarovaná ve funkci, takže platí jen uvnitř té funkce. Kdyby jsi ji stejně jak pole, vystrčil před funkci, už by vidět byla, ovšem její hodnota by byla rovna pole.length jelikož ajax je asynchronní a cyklus by nejspíše skončil dřív, než by se prováděla ta anonymní funkce.

Nefunguje to, protože není ošetřená adresa, která se vytváří:
xmlhttp.open("GET","http://www.j-jaburek.tk/etc/title.php?url="+encodeURIComponent(pole[i].href)+"&i="+i);

Na vytváření té odpovědí existuje v php funkce
echo json_encode(array("i"=>$_GET["i"], "title" => $zjstenyTitulek));
Fisir
Profil
Reaguji na Keeehiho [#14]:
existuje v php funkce
Já vím. V PHP skriptu je použita.

Děkuji ti, ale má to stále mouchy. Titulek se zjistí pouze pro poslední odkaz na stránce. (Přesněji: Dotazy se pošlou na server všechny, ale title se přidá pouze k poslednímu odkazu.)
Chamurappi
Profil
Reaguji na Keeehiho:
Ajaxový požadavek musí vypadat takto
Nemusí. Stačí, když si někde udrží hodnotu proměnné i, posílat si ji tam a zpátky přes server je divné.


Reaguji na Fisira:
Za koncem ifů a funkcí děláš zbytečně středníky.
Keeehi
Profil
Fisir:
Já vidím titulky všude, kde mají být.

Chamurappi:
V rámci kódu v [#12] ta vypadat musí. To že by se to dalo udělat celé nebo jen část jinak, to nepopírám.
Fisir
Profil
Reaguji na Chamurappiho [#10]:
Za koncem ifů a funkcí děláš zbytečně středníky.
Já vím. Ale jsem zvyklý je tam dělat.

Reaguji na Keeehiho [#11]:
Já vidím titulky všude, kde mají být.
Tak se zkus podívat třeba na www.j-jaburek.tk/clanky/novy-web. Titulek je pouze na odkazu „článek o vývoji“.
Chamurappi
Profil
Reaguji na Keeehiho:
V kódu [#12] jsi zapomněl zmínit, že JSON.parse nefunguje ve všech prohlížečích.

Pokud se takovýhle cyklus:
for(var i = 0; i < něco; i++)
{
  …
}
… nahradí za:
for(var i = 0; i < něco; i++) (function(i)
{
  …
})(i);
… bude si vnitřní i pamatovat hodnotu nezávisle na vnějším i.
Keeehi
Profil
Tak jsem celé překopal:
function getTitles(){
     for(i = 0; i < poleii.length; i++) {
        if(
        poleii[i].href.search(/j-jaburek.tk/) != -1 && 
        poleii[i].href.search(/javascript:/) == -1 &&
        poleii[i].href.search(/mailto:/) == -1
        ){
            if(poleii[i].title == "" || !poleii[i].title){
                    ajax(i);
              }
        }
    }
}

function ajax(i) {
    var xmlhttp;
    
    if (window.XMLHttpRequest){
        xmlhttp=new XMLHttpRequest();
    } else {
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    
    xmlhttp.open("GET",".href),true].href),true].href),true]http://www.j-jaburek.tk/etc/title.php?url="+encodeURIComponent(poleii[i].href),true);
    xmlhttp.onreadystatechange = function(){
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            var odpoved = JSON.parse(xmlhttp.responseText);
            poleii[i].title = odpoved.url;
        }
    }

    xmlhttp.send(null);
}

Už tam není potřeba posílat to i, takže není ani třrba využívat JSONu, ale klidně tam může zůstat. S eval by to mělo fungovat i ve starších prohlížečích
var odpoved = JSON.parse(xmlhttp.responseText) || eval("("+xmlhttp.responseText+")");

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: