JQuery - att koppla sig till händelser

Från Webbling
Version från den 12 januari 2019 kl. 21.06 av PGJ (diskussion | bidrag) (→‎Direkta och delegerade händelsehanterare)
(skillnad) ← Äldre version | Nuvarande version (skillnad) | Nyare version → (skillnad)
Hoppa till: navigering, sök

I webbläsaren inträffar det många typer av händelser. Detta kan vara alltifrån att en användare klickar på något, till att sidan meddelar att den ska laddas ur och att en annan sida ska laddas in istället. Man kan skriva kod som kopplar sig till dessa händelser och som kommer att köras när händelsen inträffar. På så vis kan vi skapa mycket mer interaktivitet i vår webbsida och vi kan bygga upp skräddarsydda komponenter som gör i stort sett vad vi vill. Att kunna koppla sig till händelser är en av de viktigaste byggstenarna som krävs för att kunna skapa interaktiva webbapplikationer!

on

Den mest använda jQuery-metoden för att koppla sig till händelser är on. Med denna kan man koppla sig till i stort sett alla typer av de händelser som kan tänkas ske i webbläsaren.

Vi börjar med ett kort exempel som kommer att göra så att en funktion körs varje gång användaren klickar på en knapp.

See the Pen xZdQGx by Patrik Grip-Jansson (@PGJ) on CodePen.

Det första vi gör är att söka reda på vårt button-element. Därefter anropar vi metoden on på sökresultatet för att koppla en händelsehanterare till knappen. I sitt grundutförande tar on ett par parametrar, nämligen...

Lista med händelser

on:s första inparameter anger vilken händelsetyp vi vill koppla oss till. Det kan finnas olika typer av händelser som är specifika för vissa typer av objekt. Det finns även händelser som är tillgängliga för i stort sett alla typer av objekt. Det kan vara bra att kolla igenom dokumentationen för den typ av objekt som du tänker koppla dig till. Där finner du tillgängliga händelser dokumenterade.

I vårt exempel väljer vi att koppla oss till händelsetypen click. Denna inträffar varje gång någon trycker på något. Vilket ju onekligen är en passande händelse att använda på en knapp.

Skulle man vilja, kan man koppla sig till flera händelser samtidigt. Man anger då de olika händelserna som en sträng där varje händelsenamn är åtskilt av ett mellanslag. Ungefär som när vi anger flera CSS-klasser samtidigt.

Händelsehanterare

Som sista on-parameter skickar vi med den funktion som vi vill ska köras när händelsen inträffar. Detta kan vara en existerande funktion eller också kan vi skapa en ny, anonym funktion. För att lättare kunna underhålla kod och göra den mer läsbar är det att rekommendera att man använder namngivna funktioner.

I vårt exempel, så skapar vi alltså en koppling som gör att när händelsen click inträffar så körs vår funktion Tryckt. Man brukar kalla denna typ av funktioner för händelsehanterare. Det är viktigt att försöka hålla koden i händelsehanterare så snabb som möjligt. Speciellt då det handlar om händelser som inträffar ofta. Gör vi inte detta kan vår applikation börja gå långsamt för att det tar långt tid att hantera varje händelse.

I exemplets händelsehanterare görs inget superspeciellt. Vi ökar bara antalet gånger som användaren tryckt på knappen.

Eftersom vi kommer att ändra på span ofta, så söker vi direkt fram den en gång för alla och spar undan en referens till elementet i variabeln $span. Detta är en bra vana att göra så här. Det spar mycket tid och datorkraft när man bara söker fram sakerna då det verkligen behövs och sedan sparar undan resultatet för kommande användning.

Händelser kopplas förstås bara till de element som redan existerar när vi kallar på on-metoden. Om vår kod skulle lägga till en extra knapp i sidan efter det att vi genomfört kopplingen, så kommer den nya knappen inte att bli kopplad till vår händelsehanterare. När vi lägger till objekt dynamiskt i sidan, måste vi alltså se till att vid behov koppla in de behövliga händelsehanterarna.

Namespaces

Det går att koppla flera händelser av samma typ till ett och samma element. Det gör att det kan vara svårt att hålla reda på de olika händelsehanterarna, speciellt gäller detta när vi ska ta bort dem ifrån elementet. Vi måste ju på något sätt kunna särskilja på de olika händelsehanterarna, så vi enbart tar bort de som ska bort och låter övriga vara kvar. En metod för att lösa detta är "namespaces".

För att ange ett namespace för en händelse så lägger vi till en punkt och därefter namnet på vår namespace. Istället för click hade vi i vårt exempel kunnat köra något i stil med click.exempel. Detta gör det enklare att ta bort händelsen eller att trigga den specifika händelsen.

one

När vi har händelser som vi bara vill hantera en enda gång, kan vi använda oss av one. Denna metod fungerar precis som on, med den skillnaden att den kan inträffa maximalt en gång. Så fort den inträffat och hanterats så kopplar jQuery bort händelsehanteraren.

I övrigt finns inte mycket att säga om denna metod. Allt som gäller för on gäller för denna också.

off

För att koppla ifrån en händelsehanterare ifrån ett element använder man sig av metoden off. Det finns lite olika sätt på vilket man kan ange vad som ska kopplas ifrån. Det vanligaste är att man som inparameter skickar med en sträng. I strängen anger man namnet på en eller flera händelser som ska kopplas ifrån.

Du kan även kalla på off utan några som helst parametrar. Då tas alla händelsehanterare bort ifrån elementet.

Mer om händelsehanterare

I vårt första exempel skapade vi en mycket enkel händelsehanterare. För att kunna skapa mer avancerade händelsehanterare behöver vi titta närmare på de möjliga inparametrar som hanteraren kan ta emot. Om vi anger att vår händelsehanterare ska ta emot en inparameter kommer vi att få ett Event-objekt. Detta innehåller information om händelsen. Det möjliggör även att vi kan ändra på saker som har med händelsen att göra.

Event-objektet

jQuery skapar en ett eget event-objekt för händelser. Detta skiljer sig något ifrån hur webbläsarens egna event-objekt ser ut. Anledningen till att man skickar med en custominiserad version är att man vill normalisera händelseinformation, så att den ser likadan ut oavsett vilken webbläsare man kör på. Vi behöver alltså inte bry oss i om användaren har en "konstig" webbläsare som ställer till med några knasigheter när händelser inträffar. I de flesta fall klarar jQuery av att fixa till dessa olikheter och den tillhandahåller oss med ett event-objekt som är likformigt.

Det finns en uppsjö av information i event-objektet. Vi ska titta på några utvalda, viktiga värden. Om du vill se vad som mer är tillgängligt kan du titta på jQuerys dokumentation.

pageX och pageY

Ett värde som vi kan läsa ut ifrån event-objektet är vilken position som muspekaren befann sig på när händelsen inträffade. Detta kan ju vara av intresse när vi kopplar en händelse till ett musklick. Vissa typer av händelser levererar inte denna information. I dessa fall är värdena undefined.

Vi kör ett exempel där vi informerar om vilken position som användaren klickade på.

See the Pen qbmzYa by Patrik Grip-Jansson (@PGJ) on CodePen.

I exemplet kopplas vår händelsehanterare till sidans body. Alla klick som utförs på denna area kommer att trigga igång en händelse. För att se till att body täcker hela sidan har vi lagt till lite extra CSS. I övrigt påminner exemplet starkt om tidigare exempel.

pageX anges som antal pixlar ifrån dokumentets högra kant. Det vill säga, inte ifrån webbläsarens kant, utan ifrån kanten på den vy som visar dokumentet. pageY anges som antal pixlar ifrån dokumentets topp. Y-axeln är omvänd mot vad vi är vana med och desto längre ned muspekaren befinner sig, desto högre blir pageY-värdet.

target

Vi kan få ut vilket element som genererade händelsen. Detta kan vara ett underobjekt till det objekt som har händelsehanteraren. I vårt klickexempel ovan, så genereras händelsen faktiskt inte alltid direkt i body, utan i vissa fall är det sidans andra element som triggar igång händelsen. Händelsen "bubblar" sedan upp till elementets föräldrar (se mer nedan om "Bubbling").

Vi gör om föregående exempel lite och skriver ut vad som genererade händelsen.

See the Pen LGyKgW by Patrik Grip-Jansson (@PGJ) on CodePen.

Om du provkör exemplet så ser du att vi får olika objekt beroende på var vi klickar.

currentTarget

I vissa fall kanske vi vill ha reda på vilket element som händelsehanteraren är kopplad till. Kanske vi har kopplat samma händelsehanterare till flera olika element och vill kunna göra något speciellt beroende på vilket element som triggas. Detta kan vi läsa ut med currentTarget.

Dock så behöver man oftast inte använda sig av detta värde. Variabeln this är nämligen automatiskt satt till just det element på vilket händelsen inträffade.

which

Ibland behöver vi veta exakt vilken tangent eller musknapp som triggade igång en händelse. Detta kan vi läsa ut med hjälp av which.

För mushändelser kommer denna att sättas till;

  1. Vänstra musknappen
  2. Mittersta musknappen
  3. Högra muskappen

Om händelsen triggades igång av ett tangenttryck kommer which att innehåll teckenkoden som motsvarar den knappkombinationen som utfördes. Om det är en enda knapp som trycktes ned erhåller du det Unicode värde som motsvarar tecknet på den tangenten. Om det är ett kontrolltecken eller om det är en kombination av tangenter som tryckts ned, så blir det mer komplicerat att tolka. Se KeyboardEvent.key för en mer ingående beskrivning av hur värdet ska tolkas.

Andra värden

Det finns som sagt många fler värden som kan läsas ut. Se event-object för mer information om tillgängliga värden.


Bubbling

Man brukar säga att händelser i webbläsaren "bubblar" upp. Vad detta betyder är att en händelse först triggar igång alla händelsehanterare på det element den inträffade på, därefter bubblar händelsen vidare upp och triggar igång eventuella händelsehanterare som är angivna för element som ligger ovanför (dvs, föräldraelement till elementet som triggade händelsen). Händelsen fortsätter att bubbla upp genom alla föräldraelement, ända upp till body och document. Detta innebär alltså att när en händelse inträffar kan en rad händelsehanterare triggas igång. Dessa händelsehanterare kanske gör helt olika saker.

Styrning av "bubbling"

Ibland kanske man inte vill att en händelse ska bubbla vidare upp till ovanliggande element. Kanske man vill ersätta det "vanliga" beteendet med ett custom beteende och därför vill vara ensam om att hantera händelsetypen. Detta kan man åstadkomma genom att använda ett par sig av några metoder som är inbyggda i event-objektet.

event.stopPropagation()

Efter det att en händelsehanterare anropar metoden event.stopPropagation() kommer händelsen att sluta bubbla vidare. Om det finns flera händelsehanterare på som är anslutna till samma element, så kan dessa triggas. Dock så kommer inte händelsehanterare på föräldraelement att triggas.

Om vi vill stoppa händelsen ifrån att nå även andra händelsehanterare på nuvarande element, måste vi använda den metod som vi beskriver under nästa rubrik.

event.stopImmediatePropagation()

Händelsen kommer inte att bubbla vidare och den kommer inte ens att nå andra händelsehanterare på nuvarande element (om de inte redan körts).

Samma sak händer faktiskt om ens händelsehanterare returnerar false. Dock är det ett gammalmodigt sätt att göra detta på. Så använd event.stopImmediatePropagation() om du vill stoppa händelsen ifrån att nå vidare.

event.preventDefault()

Om vi anropar event.preventDefault() kommer inte defaultbeteendet för elementeet att genomföras. Ett exempel på det skulle vara om vi har en händelsehanterare kopplad till a-element och vi kallar på event.preventDefault(), då skulle inte webbläsaren följa länkarna. Dock så kommer händelsen ifråga att bubbla vidare till andra händelsehanterare.

Direkta och delegerade händelsehanterare

Hitintills har vi mestadels koncentrerat oss på direkta händelsehanterare. Det vill säga händelser inträffar på ett element och detta triggar direkt igång de händelsehanterarna som finns på elementet ifråga. Detta är den vanligaste typen av händelsehanterare.

Vi har nämnt att händelser bubblar uppöver till ovanliggande föräldraelement. Det gör att element kan få händelser som inträffat på underliggande element. Om vi vill kan vi skapa en händelsehanterare som enbart är till för att hantera de händelser som inträffar i dessa underliggande element. jQuery har speciellt stöd för detta och det kallas för delegerade händelsehanterare. De underliggande elementen har delegerat ansvaret för händelsehanteringen till sina föräldraelement.

Vi skapar delegerade händelsehanterare genom att skicka med en selektor-sträng som anger vilka underelement som ska omfattas. Här är ett exempel:

See the Pen JGNgWr by Patrik Grip-Jansson (@PGJ) on CodePen.

I exemplet har vi skapat en div som innehållet ett antal knappar. Vi vill att div:en ska hantera händelserna för alla knappar. I vår on skickar vi därför med en selektor-sträng som andra inparametern. Denna väljer ut alla button som finns inuti vår div. Denna händelsehanterare kommer inte att triggas om vi klickar "var som helst" inuti div:en. Den kommer bara att handha de klickhändelser som inträffar på knapparna.

I vår händelsehanterare kommer this att vara satt till det element som triggade händelsen. Vi kan därför enkelt plocka ut namnet på knappen som användaren klickade på.

Fördelar med delegerade händelsehanterare

En fördel med att skapa denna typ av delegerad händelsehanterare är att vi kommer att få händelser från alla underelement, oavsett när de lades till. Så om vi lägger till dynamiska underelement kommer deras händelser också att trigga den delegerade händelsehanteraren. Detta skiljer sig alltså ifrån hur vanliga, direkta händelsehanterare fungerar. Om vi vet att vi kommer att ha många dynamiska förändringar i vår applikation, kan det var enklare att skapa en delegerad händelsehanterare som hanterar alla nya element istället för att specifikt koppla händelsehanterare till de nya elementen.


Skillnad mellan vanlig bubbling och delegering

Vad är då skillnaden på att ha en delegerad händelsehanterare och att bara ha en vanlig hanterare som triggas av bubblande händelser. För det är ju som så att vår div faktiskt skulle nås av klickhändelserna ifrån knapparna även om vi inte hade med selektor-strängen. Om detta vore en vanliga hanterare skulle vi behöva göra mycket mer arbete. Främst skulle vi behöva hantera det faktum att alla typer av klick skulle trigga hanteraren, oavsett var vi klickar inuti div:en.

Mer om händelser

Det finns fler saker man kan göra med händelser. Vi har vare sig gått igenom alla tillgängliga metoder eller alla tillgängliga värden. Vill du veta mer kan du titta på jQuerys dokumentation. Dock bör ovanstående räcka till i de flesta normalfall. Så om du hängt med i denna aktivitet har du en bra grund att stå på!

Nästa aktivitet

jQuery - AJAX