XHTML Strict - élet target="_blank" nélkül

Nem kis meglepetést okozott, amikor első validálásom hibái között feltűnt a there is no attribute "target" szöveg. Mint később kiderült, a HTML4 egyáltalán nem támodatja ezt az attribútumot. Mit lehet tenni, ideiglenesen kigyomláltam a forrásból ezt, a külső linkekhez univerzálisan használt megoldást.

Mielőtt azonban bárki használatba venné az érfelvágáshoz előkészített pengéket, gyorsan megjegyzem, hogy csak a Strict DTD szerint hiba a target attribútum. A Transitional tipussal vígan használhatjuk, hasonló disznóságokkal együtt. Azonban ha a teljes szabványosságot tűztük zászlónkra (és miért ne tettük volna), akkor a Transitional-féle megalkuvásnak helye nincs, tűrjük fel az ingujjakat!

Szokás szerint rágoogliztam, mi is a helyzet a témában. Természetesen mások is felfigyeltek a problémára, sok különböző megoldást is ajánlottak. Most jöjjön itt a végső megoldás, ami sok cikkből és véleményből csapódott le, szokás szerint egy kicsit felturbózva.

Voltak jó, és kevsébé jó ötletek is. Jó például, a rel="external" megjelölés használata amivel egy majdani szkript számára jelöljük (XHTML-barát módon) mik a külső ablakba kívánkozó linkek. Rossz ötlet pedig base tag használata (ilyenkor minden link új ablakba nyílik meg az érintett lapon), vagy ha Javascript segítségével szúrjuk be (anchor.target = "_blank";) a hiányzó attribútumot. Hogy ez a második miért nem tetszik? Pont a target attribútumot szeretnénk áthidalni amit a szabvány nem támogat. Semmi garancia nincs, hogy ez a megodlás meddig fog működni a böngészőkben, főleg azokon az oldalakon, akik magukat szabványosként jelölik meg.

Az általam választott módszer szerint az ablakot egy szkript nyitja meg, valahogy így:

<a onclick="window.open(this.href, '_blank'); return false;" href="...

Következő feladat a csúnya onclick attribútum eltüntetése. Erre kézenfekvő megoldás, ha egy központi helyen, a body-ban kezeljük le a felbukkanó eseményt. Ezt megtehetjük így is:

<body onclick="externalLink();">

Vagy sokkal elegánsabban: ha a szkriptünk betöltődést követően odaláncolja magát a document objektumhoz.

document.onclick=externalLink;

Még sokkal szebb lenne, az új event modelek hazsnálatával (a document.onclick=... heylett document.attachEvent(...)), azonban egy Safari bug miatt ilyenkor nem tudnánk leállítani az alapértelmezett eseményt, nevezetesen azt, hogy a link (az új ablakon kívül) az aktuális ablakban is megejelenjen, úgyhogy ez elvetve.

Itt oda is adhatnám a letisztázott szkriptet, és vége is lehetne a cikknek, de nem! Az a megoldás, hogy kizárólagosan elvegyük a document onclick eseményét egyszerűen nem tetszik. Ennek a szkriptnek a háttérben kell futnia, csupán egy COPY-PASTE -et igényleve a webmestertől, de a jelenlegi megoldás túl sok ponton összeütközhet a lapon haznált egyébb szkriptekkel. Így most jöjjön a rugalmas változat:

function targetBlank(event) { event = event ? event : window.event; var target = event.srcElement ? event.srcElement : event.target; while (target.nodeName.toLowerCase() != "a" && target.parentNode != null) target = target.parentNode; window.open(target.getAttribute("href"), "_blank"); // DOM if (event.cancelable) event.preventDefault(); // IE return false; } function targetBlankBind() { var tags = document.getElementsByTagName("A"); var i; for (i=0; i<tags.length; i++) if (tags[i].getAttribute("rel") == "external") tags[i].onclick = targetBlank; } if (window.attachEvent) { // IE window.attachEvent("onload", targetBlankBind); } else { // DOM window.addEventListener("load", targetBlankBind, false); }

Szépen sorjában: a targetBlank funkció végzi a link megnyitását (pontosabban benne a window.open). Régi stílusú eseménykezelésről lévén szó az event objektumot is másként kapjuk meg a különböző böngészőkben. Második feladat a event.target kinyerése, azaz az éppen klikkelt objektumé (nem összetévesztendő a target attribútummal, itt az esemény forrását jelöli). Az esemény forrása lehet egy, az A tagbe ágyazott másik elem is (SPAN, IMG), úgyhogy mindaddig lépkedünk felfele a DOM fában amég meg nem találjuk a linkünket jelző A taget. Majd a nagy aktus, az ablak megnyitása a megklikkelt objektum href attribútumával. Legvégül pedig az alap esemény leállítása (a link normál működésének - azaz, hogy megjelenjen a helyi ablakban - megakadályozása).

A targetBlankBind nem tesz mást, mint végigmegy a dokumentum linkjein, és a rel="external" attribútummal rendelkezőkre ráaggatja az előbb tárgyalt függvényt az onclick esemény kezelésére.

Az alsó blokk nem más, mint egy késleltetés. A linkeket csak akkor dolgozhatjuk fel, ha mind letöltődött, ezért a bindHandlers-t a window.onload eseményéhez kötjük, itt már bátran használhatunk új stílusú kötést, sőt szükséges is, mivel a régi stílusú kapcsolat összeütközést eredményezne más onload-ot használó szkriptekkel.

Külső linkek