Autor Zpráva
Alťák
Profil
Ahoj,

mám problém s jedním kouskem kódu a nemůžu pochopit, co je špatně. Má situace:

Snažím se vytvořit kód, který po načtení stránky automaticky zajistí, že bude vytvořen obsah stránky. Na položky obsahu se dá kliknout a tím se uživatel přemístí na požadované místo.

Toto je můj dosavadní kód umístěný v body:

<ul id="faq_list"></ul>
 
<a name="q_1" rel="faq"></a>
<h3 name="q_1">otázka 1</h3>
<p>nějaká odpověď</p>
 
<a name="q_2" rel="faq"></a>
<h3 name="q_2">otázka 2</h3>
<p>nějaká odpověď</p>
 
<script type="text/javascript">
 window.addEventListener('load',createFaqList,false);
 
 function createFaqList() {
  var faq = document.getElementById("faq_list");
  var i = 0;
  
  while (document.getElementsByTagName("a")[i] != undefined) {
   var hyperlink = document.getElementsByTagName("a")[i];
   
   if (hyperlink.rel == "faq") {
    var li = document.createElement("li");
    var a = document.createElement("a");
    a.setAttribute("href", "#"+hyperlink.name);
    a.innerHTML = document.getElementsByName(hyperlink.name)[1].innerHTML;
    li.appendChild(a);
    faq.appendChild(li);
   }
   
   i++;
  }
 }
</script>

Problém nastává při použití metody "faq.appendChild(li);" - nastane nějaký záhadný bug a do stránky se vloží spooousty elementů li. Prohlížeč to přirozeně po chvíli zastaví.

Máte nějaké nápady? Našli jste chybu? Už jsem zkoušel kdovíco, ale zdá se, že prohlížeč prostě nechce pobrat že chci vložit link do položky seznamu.

Budu vděčný za jakékoliv návrhy.
Tori
Profil
Představte si to jako iteraci nad obyčejným polem, od indexu 0 do konce. Když jsem u indexu třeba 3, narazím na vyhovující prvek (prvek.rel === "faq") a přidám na začátek pole nový prvek. Tím se všechny prvky posunou o jeden doprava a aktuální prvek už nebude mít index 3, ale 4. Při další iteraci tedy opět najdete vyhovující prvek (ten samý, co v předchozí iteraci), a tak to cykluje do nekonečna.
Tomu cyklování lze zabránit několika způsoby, ale proč rovnou nepoužijete jako kotvy ID nadpisů? <h3 id="q_1">Otázka 1</h3> Mohl byste tak vyhodit duplicitní kotvy na ř.3 a 7, a místo kolekce <a> prvků procházet kolekci nadpisů.
_es
Profil
Alťák:
kód, který po načtení stránky automaticky zajistí, že bude vytvořen obsah stránky
Aký je vlastne zmysel daného kódu? Prečo nie je ten „obsah“ normálne ako HTML obsah?

document.getElementsByTagName("a") je „živá“ kolekcia, teda sú v nej všetky, aj neskôr pridané, prvky, preto v tvojom kóde nastane nekonečná slučka, viď aj vysvetlenie v [#2] Tori. Všetky odkazy máš aj v kolekcii document.links.
Chamurappi
Profil
Reaguji na Alťáka:
Našli jste chybu?
Krom zmíněného problému:
1) Metoda window.addEventListener nefunguje ve všech prohlížečích.
2) Kotva pomocí name na <h3> také nebude fungovat ve všech prohlížečích, stejně tak to <h3> nepůjde všude najít metodou getElementsByName (poněvadž name na nadpis nepatří).
3) Používáš zbytečně setAttribute.
4) Atribut rel na odkazu vyjadřuje vztah stávající stránky k cílové. Není to prostor vyhrazený pro libovolnou změť znaků…
5) Odkaz hledáš zbytečně dvakrát (na řádcích 18 a 19).
Alťák
Profil
Díky všem za reakci. Problém s vkládáním odkazů si už uvědomuji, uvedené chyby se pokusím odstranit a kód tak optimalizovat.
Myslím, že vlákno můžete uzavřít. Ještě jednou díky.
Chamurappi
Profil
Reaguji na Alťáka:
Já bych to napsal cca takhle:
function createFaqList()
{
  var faq = document.getElementById("faq_list");
  for(var i = 0, h; h = document.getElementsByTagName("h3")[i]; i++)
  {
    if(!h.id) continue;
    var li = document.createElement("li");
    var a = document.createElement("a");
    faq.appendChild(li);
    li.appendChild(a);
    a.href = "#" + h.id;
    a.innerHTML = h.innerHTML;
  }
}
Nebo takhle:
function createFaqList()
{
  var faq = [];
  for(var i = 0, h; h = document.getElementsByTagName("h3")[i]; i++)
    if(h.id)
      faq.push("<li><a href=\"#" + h.id + "\">" + h.innerHTML + "</a>");
  document.getElementById("faq_list").innerHTML = faq.join("");
}

Nadpisům bych nedával name (ani <a name> před ně), ale jen id.
Alťák
Profil
Dobrá řešení - abych pravdu řekl, nevěděl jsem ani, že se dá for cyklus takovým způsobem zapsat. Jsem zvyklý, že v prostřední sekci je vždy něco jako " i < h ".
Deklarace proměnné h přímo v té sekci je promyšlená. Myslím si správně, že to funguje tak, že pokud už prohlížeč nenalezne h s indexem i, tak vrátí hodnotu false a tím se cyklus for ukončí?

Určitě navrhované řešení vyzkouším. Díky
Radek9
Profil
Alťák:
tak vrátí hodnotu false
Přesněji řečeno vrátí undefined, což se překonvertuje na false.

Chamurappi:
A nebude se pořád dokola volat metoda getElementsByTagName? Pokud ano, nebylo by lepší si ten NodeList uložit ještě do nějaké proměnné?

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