Philip Nunnegaard har bragt dette til os:
Jeg er ikke pædagog, men jeg kan da godt prøve. ^^
Alle elementerne i HTML, er objekter, og de har indbyggede metoder til
at tildele event-handling.
Og bare for at forhindre misforståelser, så dækker det fine ord
"event-handler" over en funktion, der kaldes, når en given hændelse
(event) sker.
En event-handler er altså en funktion. (Men en funktion er først en
event-handler, når den bliver sat til at blive kaldt ved en event).
Den indbyggede funktionalitet, kan faktisk håndtere mere end een
event-handler for hver event.
Man kan sige, at on/event/ (onclick f.eks.) er i virkelighed en liste
eller et array.
Bruger man objektets indbyggede funktionalitet, tilføjes funktionen til
elementets eksisterende event-handlere for den aktuelle event.
Men bruger man inline versionen - onclick="goer_noget();" - overskriver
man listen, og fjerner altså andre handlere, der kan være tilføjet. Og
det gælder også, hvis man i javascript bruger muligheden for blot at
skrive elm.onclick=goer_noget;
Og forskellen på unobtrusive og inline er i virkeligheden, at
unobtrusive bruger objektets funktionalitet til håndtering af
eventhandlere, mens inline overskriver objektets variable (- som i
virkeligheden emm. burde være private, så de ikke kan tilgås direkte).
Så "unobtrusive", er altså også lidt mere end blot at skille js ud fra
HTML'en, for skille funktionalitet fra indhold.
Og hvordan bruger man så objectets indbyggede funktionalitet?
I al sin enkelthed, gør man det ved at kalde den objekt metode, der er
beregnet til det.
Den hedder addEvenListener() (undtagelsen er overraskende : IE<9, hvor
den hedder attachEvent()).
Der er to parametre: type og listener.
type angiver hvilken event der er tale om, og angives som en streng,
men *uden* /on/ foran; click, mousedown, keypress etc.
listener er en referance til den funktion der skal kaldes når eventen
indtræder. I js, gøres det ved at give funktionsnavnet *uden*
paranteserne.
Se evt. også
https://developer.mozilla.org/en/DOM/element.addEventListener
(der er en tredie mulig parameter, som bruges til at forhindre at
eventen kaldes, hvis der er tale om en event der "bobbler op" fra et
andet element - skal ikke komme ind på det yderligere her.)
Så hvis man nu vil skrive
<a href="" onclick="goer_noget()">Linktekst</a>
som unobtrusive?
Man er til at begynde med nødt til at kunne lokalisere anchor elementet
i sin js. Det enkleste er, at give objektet et id (ikke som Philip
foreslår class; class bruges til fomattering, ikke funktionalitet), men
er der andre måder at finde elementet, er det ikke nødvendigt. (I mit
script til forme, f.eks. tildeles en eventhandler til alle elementer af
en bestemt type - men det er nok oftere man har brug for et bestemt
element, og til det er id uovertruffen.)
Vi ændrer altså HTML'en til:
<a href="" id="mit_link">Linktekst</a>
I js skal vi så tildele en eventhandler til det element, der har
id="mit_link". F.eks.:
var linket = document.getElementById('mit_link');
linket.addEventListener('click', goer_noget); //kun browsere og IE9
[Det kan skives sammen -
document.getElementById('mit_link').addEventListener('click',
goer_noget);
- men jeg foretrækker at skille tingene for overskuelighedens skyld.
Jeg har normalt også en test på om linket også er fundet - se evt.
tidligrere eksempel - for at undgå fejlmeddelelser, hvis noget går
galt.]
Og hermed har man så tildelt den samme funktionalitet på unobtrusive
vis.
Men prøver man ovenstående, går det med stor sandsynlighed galt.
For elementet med id="mit_link" eksisterer først når dokumentet er
loadet, mens udførelsen af js ikke venter på at det sker. Så variablen
linket vil sandsynligvis være 'undefined' eller noget andet, man ikke
kan bruge til noget, og man vil få fejlmeddelelse(r) - og klik på
linket, vil ikke udføre den handling man ønsker.
Løsningen er, at tildele event-handleren i en onload på window (eller
body).
Den bør man så også tildele unobtrusive - ellers er der ikke rigtig
nogen mening med alle krumspringene. Altså
window.attachEventListener('load', InitDokument);
function InitDokument() {
var linket = document.getElementById('mit_link');
linket.addEventListener('click', goer_noget); //kun browsere og IE9
}
function goer_noget() {
// gør noget!
}
Forskellen på ovenstående og det tidligere eksempel, er at jeg i
eksemplet bruger en js funktion (SetEvent) til at tildele
eventhandlerne.
Det skyldes, at i IE<9 hedder den metode der tildeler eventhandlere til
elementerne (objekterne) noget andet. Og det bliver for uoverskueligt,
at skulle teste for det, hver gang der skal tildeles. Derfor funktionen
SetEvent() i det tidligere eksempel. Den kalder blot den rigtige
(browserafhængige) metode, for det element der angives i parametrene.
function SetEvent(elm, evt, fnc) { // sætter event handlere på
elementer
if (elm) {
if (elm.addEventListener) { // for rigtige browsere
elm.addEventListener(evt, fnc, false);
}
else if (elm.attachEvent) { // for IE
elm.attachEvent('on'+evt, fnc);
}
}
}
Håber så det kaster lidt mere lys, og måske også lidt mere forståelse,
hvorfor det er en god idé at gøre tingene unobtrusive.
Ellers må jeg se om jeg kan finde en større fakkel. :D