» direct naar zoek en menu

Tijdschrift voor webwerkers » Artikel #96

Links die zich gedragen - Structuur, presentatie en gedrag

Het is een goede gewoonte om structuur, presentatie en gedrag gescheiden te houden in je websites. Structuur (de markup en content) mag geen presentatie bevatten, zoals <font> en <center> tags of tables voor opmaak. Presentatie zou zich verre moeten houden van gedrag. Maar stel nou dat je toch dat nieuwe venster wilt openen, of een passende popup wilt tonen... Hoe doe je dat?

Zoals inmiddels wel bekend mag zijn is het target attribuut niet meer toegestaan vanaf XHTML 1.0 strict. Dit kan je leuk vinden of niet, maar de reden er achter is overduidelijk: het effect van een target is gedrag, en mag dus strict gezien geen deel uitmaken van je markup. Ter geruststelling: hoewel het indirect aan bod komt is dit artikel is niet bedoeld om simpelweg een zoveelste workaround voor dat target-attribuut de wereld in te helpen. Het hoort immers de keuze van de bezoeker te zijn of ze externe links al dan niet in een nieuw venster wil openen.

Als het openen van nieuwe vensters gedrag is, zoals hierboven gesuggereerd, dan moet dit in een strikte scheiding van structuur en gedrag dus verwezenlijkt worden met JavaScript. Gedrag (en presentatie) zijn echter ondersteunende lagen: gebruik ze waar en hoeveel je wilt, maar ga er niet van uit dat ze altijd en bij alle bezoekers beschikbaar zijn. JavaScript kan bijvoorbeeld uitgeschakeld zijn door een voorzichtige bezoeker. Dit betekent dat de structuur zelf alle functionaliteit moet bevatten om de site bruikbaar te maken. Ter illustratie, een link als:

<a href="#" onclick="window.open('test.html','','width=640,height=480');">
   lorem ipsum
</a>

zal niet werken bij een bezoeker die geen JavaScript heeft, of het uitgeschakeld heeft. Deze bezoeker zou nooit te weten komen wat test.html bevat. Als de link gewoon in het href-attribuut had gestaan was dit een heel ander verhaal geweest. Een script zou het (bij diegenen waar dit werkt) veranderd kunnen hebben in de gewenste popup-link, zonder de structuur nodeloos te vervuilen. Bezoekers zonder JavaScript hadden (in tegenstelling tot bij het bovenstaande voorbeeld) op zijn minst de informatie kunnen bekijken!

Het "rel" attribuut

De URL van een link hoort dus altijd thuis in het href-attribuut, omdat dat de meest betrouwbare methode is. Wat je verder ook met die link van plan bent. Met JavaScript kan het gedrag vervolgens beïnvloed worden. Maar eerst moet je er voor zorgen dat de link door het script herkend kan worden. Een handig attribuut om hiervoor te gebruiken is het rel-attribuut. Dit attribuut geeft de relatie aan tussen de pagina en de link. Vaak wordt dit al gebruikt om links die de bezoeker van een site wegleiden visueel als zodanig te accentueren, door er b.v. een klein pijltje bij te plaatsen (wat overigens niet in alle browsers werkt):

a[rel='external']:after {
   content:"\2197";
}

Ook voor gedrag is dit attribuut prima te gebruiken. Een algemene onclick-event op het document kan kijken welk element door de bezoeker wordt aangeklikt. Blijkt het een link te zijn met een rel-attribuutwaarde waar het script wat mee kan, dan kan deze de waarde van de href gebruiken en de standaardactie van de link opheffen. Bekijk het onderstaande voorbeeld:

document.addEventListener('click', handleClick, false);

function handleClick(event) {
   var target = event.target;

   if(!/^a$/i.test(target.nodeName) || !target.getAttribute('rel')) {
      return true;
   }
}


Voor de duidelijkheid bevatten de codefragmenten die ik hier in het artikel laat zien alleen code die aan de standaarden voldoet. Het uiteindelijke werkende voorbeeld zal uiteraard wel browserspecifieke uitzonderingen bevatten.

In dit codefragment wordt bij elke klik in het document de handleClick functie aangeroepen. Het event object wat daarbij binnenkomt bevat in de target property een verwijzing naar het geklikte element. De if eronder kijkt of het een link betreft, en of deze een rel-attribuut heeft. Zo niet, dan stopt de verdere uitvoer van de functie.

Natuurlijk zijn er vele manieren om het rel-attribuut te gebruiken. Het volgende voorbeeld is dan ook maar één manier om dit te doen. Essentieel is natuurlijk wel om de uitvoer van de standaardactie van de link tegen te gaan als er een bruikbare rel is gevonden. Anders zou naast de gescripte actie ook de normale actie gewoon uitgevoerd worden. In dat geval zou de bezoeker de nieuwe pagina bijvoorbeeld dubbel te zien krijgen.

function handleClick(event) {
   
   [...]

   var rel = target.getAttribute('rel');
   var href = target.getAttribute('href');
   switch(rel) {
      case 'gallery':
         window.open(href, '', 'width=640,height=480');
         break;
      case 'lorem':
         // ...
         break;
      case 'ipsum':
         // ...
         break;
      default:
         return true;
   }

   event.preventDefault();
}

In het bovenstaande voorbeeld wordt een switch gebruikt om te kijken welke rel het betreft. Als deze niet bekend is, wordt de uitvoer alsnog afgebroken. Aan het einde wordt tenslotte de standaardactie van de klik tegengehouden als de rel wél bekend was. De onderstaande link met een rel van gallery zou bijvoorbeeld in een popup geopend worden en de pagina die de thumbnail bevat met rust laten:

<a href="foto.jpg" rel="gallery">
   <img src="thumbnail.gif" alt="lorem ipsum ..." />
</a>

Meer usability

Maar wat is nou het nut van al dit moeilijke gedoe? Tot nu toe hebben we eigenlijk alleen maar code toegevoegd ten opzichte van andere, meer gangbare, manieren. Toch biedt het scheiden van structuur en gedrag duidelijke voordelen. Het grootste voordeel wat betreft de toegankelijkheid is natuurlijk dat links het gewoon altijd doen. Maar ook qua usability zijn er voordelen.

Met een kleine toevoeging aan de code kan bijvoorbeeld gekeken worden of control, shift of alt-toetsen ingedrukt zijn tijdens het klikken van de link. Bovendien kun je registreren of de bezoeker misschien met rechts klikt in plaats van met links: niet om dit te verhinderen, maar juist om het toe te staan. Het doel is om de bezoeker hierin namelijk vrij te laten en hem of haar niet te frustreren of zelfs weg te jagen met ongewenst gedrag:

function handleClick(event) {
   if(event.which != 1 || event.shiftKey || event.ctrlKey || event.altKey) {
      return true;
   }

   var target = event.target;

   [...]
}

Om de bezoeker vooral niets op te dringen kan op deze manier de uitvoer van de code vroegtijdig gestopt worden. Zo kan de bezoeker in alle rust zelf kiezen om de links te openen in nieuwe windows, tabs, of om wat voor reden dan ook rechts te klikken op de link. Al het bovenstaande samengevoegd ziet er dan alsvolgt uit:

document.addEventListener('click', handleClick, false);

function handleClick(event) {
   if(event.which != 1 || event.shiftKey || event.ctrlKey || event.altKey) {
      return true;
   }

   var target = event.target;

   if(!/^a$/i.test(target.nodeName) || !target.getAttribute('rel')) {
      return true;
   }

   var rel = target.getAttribute('rel');
   var href = target.getAttribute('href');
   switch(rel) {
      case 'gallery':
         window.open(href, '', 'width=640,height=480');
         break;
      case 'lorem':
         // ...
         break;
      case 'ipsum':
         // ...
         break;
      default:
         return true;
   }

   event.preventDefault();
}

Het uiteindelijke werkende voorbeeld bevat zoals vermeld iets meer code dan ik hier laat zien, om onder andere rekening te kunnen houden met meerdere browsers, die het werken met events soms wat verschillend geïmplementeerd hebben.

Op deze manier heeft iedereen wat wils. De ontwikkelaar kan – met in achtneming van striktere regels – gedrag inzetten dat naar zijn mening (of die van een klant) recht doet aan de site en tegelijkertijd altijd toegankelijk is. Daartegenover staat dat de bezoeker toch helemaal vrij is om – bewust of onbewust – dit gedrag te overstemmen met een ander gedrag dat de eigen voorkeur heeft. Kortom, een doeltreffend samenspel van meerdere applicatielagen die de toegankelijkheid en usability bevorderen.

Auteur

Peter Nederlof

werkt als clientside webdeveloper bij Inpact waar hij probeert zoveel mogelijk uit script, HTML en CSS te halen zonder dat dit ten koste gaat van design, toegankelijkheid en usability.

Zijn persoonlijke site Peterned gaat (uiteraard) over scripten en dhtml.

Publicatiedatum: 07 december 2004

Let op

Naar Voren is op 18 juli 2010 gestopt met publiceren. De artikelen staan als een soort archief online. Het kan dus zijn dat de informatie verouderd is en dat er inmiddels veel betere of makkelijkere manieren zijn om je doel te bereiken.

Copyright © 2002-heden » NAAR VOREN en de auteurs