Zmenené chovanie <base> v IE 7

Internet Explorer 7 opraví súčasnú implementáciu elementu <base> tak, aby vyhovovala špecifikácii HTML 3.2. Doteraz MSIE dovoľuje použiť viaceré <base> elementy v dokumente. HTML 3.2 dovoľuje jediný <base> umiestnený v <head>.

Keďže MSIE podporuje viaceré <base> elementy, spracuje ich ako „kontajnery“ (napr. ako <div>). Platnosť <base> je pre všetky elementy až po nasledujúci <base>. CSS selektory teda môžu byť vyhodnotené nie podľa očakávaní. V IE7 bude <base> spracovaný ako nepárový tag – teda element bez možného obsahu.

IE7 bude vždy brať v úvahu iba prvý <base> element v <head>. Čo z toho vyplýva? Pre tých, ktorí dodržovali štandardy, nič, stránky budú rovnako funkčné. Pre tých, ktorí používajú viaceré <base> elementy, to predstavuje zvýšené náklady, pretože musia svoje stránky opraviť.

Via All your are belong to us, IEBlog.

Jednoduchý redakčný systém

Úpravy na redakčnom systéme pre novú verziu Izsak's Website sú hotové. Ako základ som použil lucidCMS vo verzii 1.0.11.

Jadro lucidCMS a pluginy som upravil, aby generovali aj čisté URL, pridal som podporu pre Texy!, cacheovanie stránok a upravil inštaláciu východzích pluginov.

Na Texy! fóre som uverejnil verziu lucidCMS 1.0.2 by izsak. Do finálnej verzie 1.0.20 som ešte pridal vlastný Google Sitemaps plugin, ktorý generuje sitemap súbor pre Google Sitemap službu. Upravil som tiež číslo verzie, aby bolo vidieť, že sa jedná o novšiu verziu ako 1.0.11.

lucidCMS je jednoduchý a pritom komplexný redakčný systém so všetkým potrebným na správu stránok a nie je plný zbytočných a zložitých funkcií ako napr. Drupal.

Samostatný plugin Google Sitemaps je upravený pre lucidCMS 1.0.11. Moja verzia lucidCMS 1.0.20 obsahuje upravenú verziu, aby hneď po inštalácii bol nastavený pre túto verziu redakčného systému.

Google Sitemaps plugin v lucidCMS 1.0.20 obsahuje tiež jednu značku: GoogleSitemapLink, ktorá vygeruje link element s odkazom na sitemap súbor:

<link rel="sitemap" href="/sitemap.xml" type="application/xml" />

Táto značka nie je štandardizovaná a vyhľadávače ju nepoužijú na získanie informácie ceste k sitemap súboru. V prípade Google treba stále použiť administračné rozhranie na pridanie sitemap súboru.

Do samostatného pluginu značka GoogleSitemapLink nie je implementovaná, pretože nedokážem presne určiť cestu k sitemap.xml súboru v rôznych inštaláciách a lucidCMS nemá žiadnu informáciu o použití HTML/XHTML značiek. (Značka napevno používa XHTML syntax)

Stiahnite si lucidCMS 1.0.20 by izsak.

Internet Explorer slávi 10 rokov

Windows 95 v tejto dobe oslavuje 10 rokov. Mnohý však zabúdajú, že spolu s ním Microsoft uviedol aj prehliadač Microsoft Internet Explorer 1.0, ktorý má rovnako 10 rokov.

Tento prehliadač bol stavaný hlavne ako proprietárna platforma, ktorú využijú hlavne veľké podniky a bola „pokroková“, ale v súčastnosti obsahuje málo moderných technológií, ktoré by umožnili ešte lepšie využiť potenciál webu a webdizajnérov. Internet Explorer 7 by to mal zlepšiť.

Via Internet Explorer turns 10, IEBlog.

lib.js – práca s CSS triedami

Seriál o knižnici lib.js pokračuje predstavením piatich funkcií pre prácu s CSS triedami – atribútom class="". Programovo pracovať s atribútom class je v JS dosť problematické, pretože názov vlastnosti je className, čo mnohí netušia a je treba s ním pracovať ako s textom – nie je to žiadne pole hodnôt – takže napr. na zistenie, či element má aplikovanú nejakú triedu sa používa vyhľadávanie v texte a iné metódy. Nie vždy však bývajú 100% spoľahlivé. Celú situácii zjednodušuje lib.js knižnica s ktorou ľahko pridáme, odstránime, „zameníme“, zistíme, či element má definovanú triedu a pridáme triedu za splnenia podmienky.

Pridanie/odstrá­nenie triedy

// C# syntax
void addClass(DOMString elem, DOMString className);
void addClass(HTMLElement elem, DOMString className);
void addClass(DOMString elem, DOMString className, boolean allowDuplicates);
void addClass(HTMLElement elem, DOMString className, boolean allowDuplicates);

// Java syntax
addClass(elem: DOMString, className: DOMString) : void;
addClass(elem: HTMLElement, className: DOMString) : void;
addClass(elem: DOMString, className: DOMString, allowDuplicates: boolean) : void;
addClass(elem: HTMLElement, className: DOMString, allowDuplicates: boolean) : void;

// C# syntax
void remClass(DOMString elem, DOMString className);
void remClass(HTMLElement elem, DOMString className);
void remClass(DOMString elem, DOMString className, boolean all);
void remClass(HTMLElement elem, DOMString className, boolean all);

// Java syntax
remClass(elem: DOMString, className: DOMString) : void;
remClass(elem: HTMLElement, className: DOMString) : void;
remClass(elem: DOMString, className: DOMString, all: boolean) : void;
remClass(elem: HTMLElement, className: DOMString, all: boolean) : void;

Parameter allowDuplicates funkcie addClass() určuje, či sa má trieda className pridať aj vtedy, ak ju už má element definovanú.
Parameter all funkcie remClass() určuje, či sa majú odstrániť všetky výskyty triedy aplikované na element elem. Ak nie je nastavený, odstráni sa prvý výskyt danej triedy – toto je dôležité vedieť z hladiska CSS kaskády.

Ak nie sú parameter určené, funkcie sa chovajú, akoby boli nastavené na hodnotu false.

Ukážka: funkcia SetClasses() postupne pridá/odstráni triedy elementu p aj s ukázaním funkcií parametrov allowDuplicates a all.

function SetClasses() {
  var p = getElem('p1'); // získanie referencie na odstavec

  addClass(p, 'green');
  addClass(p, 'blue');
  addClass(p, 'red');
  alert(p.className); // class="green blue red";

  addClass(p, 'red'); // nie je povolené pridanie duplikátnej triedy
  alert(p.className); // class="green blue red";

  addClass(p, 'green', true); // povolí pridanie duplikátnej triedy
  addClass(p, 'red', true); // to isté...
  alert(p.className); // class="green blue red green red"

  remClass(p, 'green'); // odstráni iba prvú triedu .green
  alert(p.className); // class="blue red green red";

  remClass(p, 'red', true); // odstráni všetky triedy .red
  alert(p.className); // class="blue green";
}

Ako sa postupne mení hodnota atribútu class="" môžete vidieť v komentároch.

Podmienené aplikovanie triedy

// C# syntax
boolean swapClass(DOMString e, DOMString c);
boolean swapClass(HTMLElement e, DOMString c);

// Java syntax
swapClass(e: DOMString, c: DOMString) : boolean;
swapClass(e: HTMLElement, c: DOMString) : boolean;

Funkcia swapClass() je veľmi vhodná na vytvorenie tzv. „on/off“ stavov. Ak triedu c má element e aplikovanú, funkcia triedu odstráni, v opačnom prípade ju pridá. Upozornenie k vnútornej implementácii funkcie si prečítajte nižšie.

Funkcia vráti true, ak element má definovanú triedu po vykonaní funkcie, false, ak triedu definovanú nemá. Návratovú hodnotu je vhodné použiť na zistenie aktuálneho on/off stavu.

Príklad:: Po kliknutí na odkaz sa čierny text a biele pozadie odstavcu #p1 zmení na červený text a žlté pozadie. Pri ďalšom kliknutí sa zmení naspäť. Príklad ukazuje použitie funkcie swapClass() na veľmi jednoduché vytvorenie (toggle) „on/off“ stavu.

<style type="text/css">
.red { color: red }
.bg-yellow { background: lightyellow }
</style>
...

<script type="text/javascript">

addLoadEvent(function() {
  addEvent('a', 'click', evt_a_click);
});

function evt_a_click(e) {
  // pri každom kliknutí sa zmení farba textu a pozadia
  var p = getElem('p1');
  swapClass(p, 'red');
  swapClass(p, 'bg-yellow');

  e.preventDefault();
}
</script>
...

<body>
  <p id="p1">test</p>
  <p><a href="#" id="a">Klik!</a></p>
</body>

Zobrazenie ukážky funkcie swapClass()

Funkcia condClass() pridá alebo odstráni triedu na základe pravdivosti parametru cond. Ak je pravdivý, trieda c bude elementu e pridaná, ak je nepravdivý, trieda bude zmazaná. Upozornenie k vnútornej implementácii funkcie si prečítajte nižšie.

// C# syntax
void condClass(DOMString e, DOMString c, boolean cond);
void condClass(HTMLElement e, DOMString c, boolean cond);

// Java syntax
condClass(e: DOMString, c: DOMString, cond: boolean) : void;
condClass(e: HTMLElement, c: DOMString, cond: boolean) : void;

Upozornenie k vnútornej implementácii swapClass() a condClass(): Funkcie pri pridávaní alebo odstraňovaní tried používajú funkcie addClass(), remClass() bez 3. parametru, čiže:

  • pri pridávaní triedy nie sú pridané duplikáty (allowDuplicates = false),
  • pri odstraňovaní triedy nie sú odstránené všetky výskyty triedy (all = false).

V prípade zložitejších prác s triedami je možné, že vám zostanú duplikáty triedy v elemente a vzniknú problémy s CSS kaskádou.

Má element definovanú triedu?

// C# syntax
int condClass(DOMString elem, DOMString className);
int condClass(HTMLElement elem, DOMString className);

// Java syntax
condClass(elem: DOMString, className: DOMString) : int;
condClass(elem: HTMLElement, className: DOMString) : int;

Funkcia hasClass() vráti počet definovaných tried className v elemente elem.

var p = getElem('p1');

remClass(p, 'red', true); // vymazanie všetkých .red tried
addClass(p, 'red', true);
addClass(p, 'blue', true);
addClass(p, 'red', true); // pridanie duplikátnej .red triedy
addClass(p, 'green', true);

alert(hasClass(p, 'red')); // element p má 2 triedy .red

Poznámka na koniec: žiadna z uvedených funkcií nevie pracovať s kolekciou (poľom) elementov. Ak chcete hromadne aplikovať triedu napr. na všetky obrázky na stránke, musíte použiť cyklus. Kód addClass(getAll('img'), 'obrazok'); nebude fungovať.

lib.js – funkcia getAll()

Ďalšou užitočnou funkciou v knižnici lib.js je funkcia getAll(). Vráti všetky elementy s daným názvom. Elementy vyhľadáva v celom dokumente, alebo iba v zadanom elemente.

// C# syntax
NodeList getAll(DOMString tagName);
NodeList getAll(DOMString tagName, DOMString parent);
NodeList getAll(DOMString tagName, HTMLElement parent);

// Java syntax
getAll(tagName : DOMString) : NodeList;
getAll(tagName : DOMString, parent : DOMString) : NodeList;
getAll(tagName : DOMString, parent : HTMLElement) : NodeList;

getAll() zjednodučuje prácu s funkciou getElementsByTagName().

  • Ak je uvedený iba parameter tagName, funkcia vráti elementy z celého dokumentu, ktoré majú daný názov elementu.
  • Ak je uvedený parameter parent (či už ako text (DOMString) alebo referencia na element (HTMLElement)), funkcia vráti všetky elementy s daným názov, ktoré sa nachádzajú v elemente parent.

Ukážka: priradenie akcie všetkým odkazom v menu.

<script type="text/javascript">
addLoadEvent(Init);

function Init() {
  var a = getAll("a", "menu"); // získenie všetkých <a> v elemente s ID "menu"
  addEvent(a, "click", evt_a_click); // priradenie akcie
}

function evt_a_click(e) {
  ...
}
</script>
...

<body>
<p id="menu">
  <a href="/">Home</a> |
  <a href="/contact/">Kontakt</a> |
  <a href="/sitemap/">Mapa stránok</a>
</p>
...

Funkcia getAll() je veľmi praktická, keď potrebujeme pracovať so skupinou elementov s rovnakým názvom (tag name). Vrátenú kolekciu (pole) prvkov je možné ľahko cyklom prejsť a upraviť. Dĺžku poľa získame štandardnou vlastnosťou polí – length.

lib.js – funkcia getElem()

minulom článku som začal písať o udalostnom skriptovaní. Vyzerá to, že séria článkov sa bude uberať aj smerom širšieho vysvetlenia funkcie knižnice lib.js. V sérii lib.js objasním funkciu niektorých častí knižnice lib.js. Budem sa snažiť používať názvy objektov podľa DOM 2: HTML.

Začneme s funkciou getElem(). Funkcia vráti referenciu na prvok v dokumente podľa ID, podobne ako document.getElementById(id). Funguje však aj v prehliadačoch bez podpory getElementById().

// C# syntax
HTMLElement getElem(DOMString el);
HTMLElement getElem(HTMLElement el);

// Java syntax
getElem(el : DOMString) : HTMLElement;
getElem(el : HTMLElement) : HTMLElement

Funkcia getElem() sa chová takto:

  • ak je argument el text, tak funkcia vráti referenciu na prvok v dokumente, ktorý ma atribút id="" rovnajúci sa hodnote el,
  • ak je argument el už existujúci prvok (HTMLElement), tak vráti tento prvok.
var elm  = getElem("menu"); // DOMString
var elm1 = getElem(elm);  // HTMLElement

// elm aj elm1 sú referenciou na ten istý prvok

Toto chovanie sa veľmi využíva v internom kóde lib.js. Umožňuje používať rôzne zápisy kódu s rovnakou funkčnosťou (v podstate preťažovanie funkcií). Je výhodné podobne písať aj vlastné funkcie, ktoré pracujú s elementami v dokumente.

Príklad: funkcia addEvent() má prvý argument element, na ktorý bude naviazaná udalosť. Vďaka internému použitiu getElem v addEvent() je možné použiť tieto zápisy, pričom každý má rovnaký význam:

var elm = getElem("menu");
addEvent(elm, "click", function() { alert("kliknutie!"); });
//alebo
addEvent("menu", "click", function() { alert("kliknutie!"); });

Funkcia addEvent() principiálne vyzerá takto:

function addEvent(el, evt, fn) {
  el = getElem(el);
  // vo funkcii bude el vždy odkazovať na prvok, či už je argument typu DOMString alebo HTMLElement
  ...
}

Udalostné skriptovanie stránok

Skriptovanie založené na udalostiach (event driven scripting) je v súčastnosti obtiažne použiť na webových stránkach, pretože prehliadače používajú veľmi rozdielne spracovanie udalostí. Ich implementácia sa veľmi vzďaľuje od DOM Events (či už úrovne 2, alebo úrovne 3).

Jednoduché použitie eventov umožňuje JS knižnica lib.js. Zjednocuje rozdielne chovania prehliadačov a zaobaľuje ich do dvoch hlavných funkcií:

  • addEvent() – pridá udalosť k daným prvkom,
  • remEvent() – odstráni udalosť z daných prvkov,

Pomocná funkcia addLoadEvent()rieši problém s naviazaním udalosti load v Opere. (Pridá dokumentu udalosť podobne ako HTML zápis <body onload="...">.)

Knižnica lib.js tiež zjednodušuje prácu s prvkami v dokumente. Dôležité funkcie:

  • getElem(id) – získa referenciu na element podľa daného ID. Ak id už je referenciou na prvok, vráti tento prvok (element).
  • getAll(name, parent) – vráti všetky elementy, ktorých názov je name a nachádzajú sa v elemente getElem(parent) (funkcia si sama zistí, či je parent element alebo ID elementu. Ak je nedefinovaný, použije objekt document).
  • getElementsByClass() – získa všetky elementy s určitou triedou. Má viacero parametrov vymedzujúcich oblasť prehľadávaných elementov.
  • hasClass(elm, className) – zistí, či element má definovanú určitú triedu.
  • addClass(elm, className, duplicates) – elementu priradí triedu className. duplicates určuje, či trieda môže byť pridaná viacnásobne.
  • remClass(elm, className, all) – odstráni triedu z elementu. all určuje, či odstráni všetky výskyty triedy.

Spracovanie (X)HTML dokumentu

Pre správne (a funkčné) použitie funkcie getElem() je potrebné pochopiť, ako je spracovávaný (X)HTML dokument:

  • HTML parser načítava dokument postupne a prvky sú dostupné pre DOM postupne. Na prvok s atribútom id="" (ID) je teda možné sa odkazovať až potom, ako ho parser spracuje.
  • XHTML dokumenty podliehajú XML pravidlám a spracuváva ich XML parser až potom, ako je celý dokument načítaný. Všetky dáta sú dostupné pre DOM až po načítaní celého dokumentu.

Poznámka: XHTML dokument podlieha XML pravidlám pri XML mime type (napr. application/xhtml+xml­).
MSIE vždy používa HTML parser.

V oboch prípadoch je kompletná štruktúra dokumentu dostupná pre DOM až po načítaní celého dokumentu, kedy je vyvolaná udalosť load objektu window (alebo document v Opere). Funkcia k tejto udalosti sa naväzuje pomocou addLoadEvent().

<head>
  <script type="text/javascript">

// funkcia getElem() sa nevykoná a beh skriptu sa skončí,
// pretože prvok s id="p1" ešte neexistuje
var p1 = getElem("p1");

// po načítaní dokumentu sa vykoná funkcia Init()
addLoadEvent(Init);

function Init () {
  // po načítaní dokumentu sú už prvky podľa ID dostupné
  var p2 = getElem("p2");
  alert(p2);
}
  </script>
</head>
<body>
<p id="p1">Odstavec 1</p>
<p id="p2">Odstavec 2</p>
</body>

Jednoduché pridanie udalosti k elementu

Dnešný článok ukončím praktickou ukážkou pridania funkcie pre udalosť na nejaký element.

Problém: Zobrazenie textu odkazu a URI na ktoré odkazuje.

Riešenie: Pomocou udalostí naviažeme na každý odkaz obslužnú funkciu evt_Kliknutie ktorá vykoná daný príkaz.

<head>
  <script type="text/javascript">
// po načítaní dokumentu zavolá funkciu Init();
addLoadEvent(Init);

function Init() {
  // získanie všetkých odkazov v prvku #p1
  var a = getAll("a", "p1");

  // elms môže byť jeden element alebo kolekcia elemetov (pole)
  // pri kolekcii elementov je udalosť naviazaná na každý objekt v kolekcii
  addEvent(a, "click", evt_Kliknutie);
}

// handler - obslužná funkcia udalosti
function evt_Kliknutie(e) {
  // objekt e obsahuje informácie o zdroji udalosti
  // vlastnosť e.currentTarget obsahuje odkaz na zdroj udalosti
  // v tomto prípade to je odkaz, na ktorý bolo kliknuté
  var a = e.currentTarget;
  // zobrazí text odkazu a cieľ
  alert(a.innerHTML +": "+ a.href);

  // zabránenie "spracovaniu" hypertextového odkazu
  e.preventDefault();
}
  </script>
</head>
<body>
<p id="p1">
  <a href="page1.html">Stránka 1</a>,
  <a href="page2.html">stránka 2</a>,
  <a href="page3.html">stránka 3</a>.
</p>
</body>

Ukážka základného priradenia udalosti pomocou funkcie addEvent.

Základné používanie udalostí s knižnicou lib.js je veľmi jednoduché. Môžeme využiť aj posielanie argumentov obslužným funkciám (handlerom), ale to si ukážeme v ďalšom článku.

Odstránenie udalosti

// priradí udalosť k elementu
addEvent("p1", "mouseover", evt_HoverEfect);

// odstráni udalosť pre element
remEvent("p1", "mouseover", evt_HoverEfect);

Odstraňovanie eventov mi nefungovalo, v podstate argumenty by mali byť rovnaké ako pri pridaní eventu. Neviem ešte, či je chyba v prehliadačoch alebo v knižnici.


Udalostné skriptovanie mne osobne umožnilo veľmi rýchlo vyvinúť komplexné, inteligentné administračné rozhranie pre jeden CMS systém. Pri dobrom návrhu programovej logiky udalostné skriptovanie šetrí mnoho času a umožňuje vytvárať univerzálne funkcie pre obsluhu formulárov (validácia, filtrovanie <select> zoznamov a iné).

Poznámka: pre jednoduchosť som používal výrazy priradenie udalosti alebo naviazanie udalost. Pre pochopenie problematiky sú tieto výrazy (podľa mňa) dostačujúce. Správne sa však vždy jedná o „naviazanie obsluhovača udalosti na udalosť“ (naviazanie handleru na event).

Obsluhovač udalosti je funkcia, ktorá sa zavolá pri nastaní udalosti. Jednu udalosť môže obsluhovať aj viacej obsluhovačov (handlerov).

Aktualizácia: Príklad nefungoval, pretože som mal na serveri starú verziu lib.js a aj preklep v HTML kóde. Opravené 10. 8. 2005 o 13:06.

Posunutie anchoru aj v MSIE

Nový projekt so sebou prináša i nové riešenia použiteľnosti a opravy pre Internet Explorer. Projekt, na ktorom robím, má fixnú hlavičku a dlhé texty skryté pomocou JS. Pri rozbalení je potrebné, aby sa nadpis textu zobrazil pod hlavičkou. So štandardným HTML a CSS kódom to nie je žiaden problém.

Problém: fixná hlavička na vrchu stránky zaberá určitý priestor. Po kliknutí na cielený odkaz (#) sa stránka odskroluje tak, že cieľ odkazu (anchor: <a name=""></a>, alebo akýkoľvek element s atribútom id="" v moderných prehliadačoch) bude na vrchu stránky (bude mať nulovú výšku od horného okraja priezoru prehliadača). Pri fixnej hlavičke sa však zobrazí za hlavičkou.
Riešenie: posunutie cieľu odkazu (anchoru) pomocou CSS o výšku navigácie, aby sa nadpis zobrazil nižšie.

Hlavička je umiestnená pomocou position: fixed a fixnej pozície pre IE a má výšku 155px.

HTML kód:

<body>
...
<div class="item">
  <a name="p1-head" id="p1-head" class="target"></a>
  <h2>Nadpis 1</h2>
  <p>Text <a href="#p1-head">odkaz</a></p>
</div>
...
</body>

Cieľ odkazu treba od nadpisu posunúť o 155px vyššie. Môže sa nachádzať kdekoľvek v dokumente, použijeme teda relatívne pozíciovanie, ktoré posunie element o danú pozíciu z jeho aktuálneho miesta v dokumente.

a.target {
  position: relative;
  top: -155px;
}

/* je tiež možné použiť a[name] selektor */

Kód je samozrejme len pre moderné prehliadače (Firefox, Opera, Safari) a preto je možné alternatívne použiť a[name] alebo a[id] selektor.

Problém v IE: ako inokedy, toto v MSIE nebude fungovať. Po dlhom testovaní som zistil, že keď sa anchoru nastavia rozmery (width, height), pričom nezáleží na display: block/inline, element posunie relatívne, ale na jeho pôvodnom mieste sa vytvorí priestor (asi prázdeno textu), ktorý má rovnaké rozmery (okrem iného sa posunie celý obsah). Tento priestor je viediť pri označení textu myšou.

Keď relatívna pozícia nefungovala, skúsil som použiť inú možnosť na posunutie elementu. Tá musela spĺňať túto požiadavku: posunúť element vyššie podľa jeho pozície vypočítanej pri position: static.

Okrem vlastnosti topje možné posunúť aj pomocou margin-top. Pri použití margin-top: -155px sa však posunie aj celý statický obsah za elementom. Je teda nutné použiť ešte position: absolute. Absolútne poziciované prvky sú vyňaté z layoutu a svojou pozíciou neovplyvňujú iné prvky. Využívam tiež ďalšiu vlasnosť absolútnych prvkov: bez udania top/right/bottom/left atribútov je ich pozícia vypočítaná ako pri position: static.

Záporný margin-top „priťahuje“ element hore a teda MSIE nevytvára žiaden duplikovaný obsah (alebo ako tú podivnú vec nazvať).

Možno to bola náhoda, ale na odlaďovanie som používal border a nie background aby som videl rozmery elementu. Po úspešnom posunutí prvku hore v MSIE a odskúšaní fungovania cieľených odkazov som odstránil border, aby cieľ nebolo vidieť. Aké však bolo moje prekvapenie, keď zrazu anchory nefungovali. Po ďalšom textovaní som zistil, že fungujú jedine, ak majú nastavený viditeľný okraj – border. Nefunguje blokové zobrazenie s rozmermi, ani iné podobné techniky. Anchory musia mať nastavený viditeľný okraj!

Výsledné CSS:

.target {
  _position: absolute;
  _margin-top: -155px;
  _border: 1px solid white; /* !musí byť, ináč posunutie nefunguje v IE! */
  _visibility: hidden; /* skryjeme prvok */
}


.target[id] {
  position: relative;
  top: -135px;
}

Kód si môžete upraviť tak, aby bol validný a použiť ho napr. v spojení s podmienenými komentármi.

Ako SPAMboty skresľujú štatistiky

SPAMboti automatizovane nepridávajú len odkazy do komentárov, vedia sa aj pridať do zoznamu spätných odkazov (napr. v systéme Pixelpost).

Photo Blog mal podľa svojich záznamov a štatistík AWStats bežiacich na hostingu približne 100 unikátnych návštevníkov mesačne a celkový počet 3500 návštev. Tieto štatistiky však obsahujú závažnú chybu: do zobrazených stránok a návštevníkov zarátavajú aj SPAMbotov. Chyba je v tom, že zobrazujú požiadavky na server, pričom SPAMbot si žiadnu stránku nepozerá. Odosiela iba na správne adresy HTTP požiadavky s vyplneným poľom Referer. Požiadavka sa zaznamená v logu serveru (číta ho AWStats) a do databázy si informáciu zapíše aj Pixelpost.

SPAMbot však neprijíma odpoveď serveru, presnejšie neinterpretuje HTML kód. Toto sa prejaví v štatistikách ako TOPlist. Požiadavka na server TOPlistu je posielaná pri načítaní obrázku v HTML kóde, čiže v tejto metóde sa SPAMboty neprejavia.

Kým som implementoval blokovanie IP adries do Pixelpostu, do jeho záznamov bolo pridaných 12 nových spätných odkazov od SPAMbotov. Za tú istú dobu (cca 3 hodiny) do štatistík TOPlistu pre PhotoBlog nepribudol žiaden nový záznam. Sledovanie štatistík pomocou obrázku v HTML kóde nezaznamenáva prístupy SPAMbotov.

Zvyšovanie unikátnych návštev na Photo Blog-u až o 30 každý mesiac podľa AWStats je úplné skreslené. Z 3500 záznamov boli až 2/3 SPAM.

Zobrazenie štatistík

Ban list

Pri mazaní záznamov z databázy som získal až 30 unikátnych IP adries, z ktorých prichádzali SPAMboti. Rozhodol som sa teda zoznam uverejniť (aj pre jednoduchšie spracovanie vo viacerých skriptoch). Zoznam blokovaných IP adries je umiestnený na adrese http://www.izsak.net/ipban/list. Zoznam je kódovaný v UTF-8, riadkovanie je UNIXové.

PS: Spomenul som si na Hruškovičovú a jej chyby metódy. Kto by len povedal, že s chybami metódy sa ešte stretneme :-).

Prístupné web aplikácie

Javascript for the masses, Anne van Kesteren:

Personally, I?m under the opinion that everything that should be indexed should work without javascript. As you don?t index applications, you don?t need a javascript off version.

Argumentov, prečo vytvárať prístupné stránky a web prezentácie je dostatok. Každý sa môže presvedčiť, že sú benefitom pre zákazníka a užívateľov. (Čo sa mi aj podarilo obhájiť na praktickej maturite.) Ako je to však s prístupnosťou webových aplikácií? Oplatí sa investovať do vývoja prístupných webových aplikácií?

V súčastnosti je pekným príkladom webovej aplikácie Gmail. Je celý postavený na JS, ktorý generuje stránky. Takto je server odľahčený od generovania HTML kódu. E-mailové rozhranie však nie je prístupné.

Webové aplikácie sú dosť špecifické produkty, ktoré sú väčšinou tvorené pre špecifické použitie a z názvu „aplikácia“ vyplýva, že takéto stránky majú „vyššiu“ funkcionalitu a tú je v súčastnosti možné dosiahnuť pomocou JavaScriptu.

Anne píše, že bohsa, ktorý má byť zaindexovaný (vyhľadávačmi), musí byť funkčný bez JS. To je dôležitý fakt, pretože ináč prehliadače nie sú schopné sa pohybovať po stránke. Toto môže byť vodítkom, či vytvoriť prístupnú aplikáciu. Administračné rozhranie CMS nie je potrebné indexovať, je väčšinou robené pre danú cieľovú skupinu a teda je možné upustiť od prístupnosti. Webové aplikácie, ktorá má používať veľká masa ľudí (verejné blogovacie systémy), by mali byť vytvorené prístupnými metódami.

Netreba si však mýliť prístupný kód s validným kódom. Validný kód umožňuje rýchlejší a jednoduchší vývoj, pri ktorom sú eliminované chyby vznikajúce nesprávnou interpretáciou kódu. Prístupný kód je taký, ktorý umožňuje zobraziť/preh­rať/vytlačiť stránku na ľubovoľnom zariadení a neobmedzuje úžívateľa pri získavaní dát.