completefrontend
Open lab My progress
THE JAVASCRIPT FIELD GUIDE

Mouse, pointer & touch

Handle clicks, hovers, drags, pens, and touch screens with mouse events, pointer events, pointer capture, and HTML drag and drop.

By the end, you can
  • 01
    Read which mouse buttons are pressedTell button from buttons, read relatedTarget, and know the order of the events in one click.
  • 02
    Choose pointer eventsHandle a mouse, a pen, and a finger with one set of events, and know why mouse events still fire after them.
  • 03
    Build dragging that doesn't breakUse pointer capture or HTML drag and drop, depending on what you build.

One set of events for every kind of pointer

People point at a web page in many ways. Some use a mouse. Some touch a phone screen with a finger. Some draw on a tablet with a pen. Whatever the device, the page needs to know three things: where is the pointer, what is it doing, and should the page react?

This lesson covers three groups of browser events:

  • Mouse events, such as click and mouseover. You still use them for normal clicks, hover, and right-click menus.
  • Pointer events, such as pointerdown. They work the same way for a mouse, a pen, and a finger.
  • Drag-and-drop events, such as dragstart and drop. The browser uses them to move an item into a drop area.
Real-life analogyPointer events are a universal remote

A universal remote has one set of buttons. The same buttons work your TV, your speaker, and your projector. Pointer events work the same way. You write one set of listeners, and they work for a mouse, a finger, and a pen. Each event also tells you which device sent it.

In real life: One remote with the same buttons for every device
In JavaScript: The same events for every device: pointerdown, pointermove, and pointerup
In real life: A light on the remote that shows the device: TV, speaker, or projector
In JavaScript: pointerType says mouse, pen, or touch
In real life: An extra that only some devices have
In JavaScript: Extra properties such as pressure (how hard a pen presses), when the device reports them
Definition

A pointer is one point that points at or touches the page: a mouse cursor, a finger on the screen, or a pen tip. A pointer event is a browser event about that point. It says where the point is, what it is doing, and which device it came from.

A pointer event says which pointer it came fromPop out in the code editor (opens in a new tab)JavaScript
const event = {
  pointerType: "touch",
  pointerId: 7,
  isPrimary: true,
};

console.log(event.pointerType);
console.log(event.pointerId);
console.log(event.isPrimary);

This code makes a small object shaped like a real pointer event. Lines 7 to 9 print three of its properties. In plain words, line by line:

  1. Line 2: pointerType is "touch", so a finger made this event.
  2. Line 3: pointerId is 7. Every pointer on the screen gets its own id number. If two fingers touch the screen, each finger has a different id, so your code can tell them apart.
  3. Line 4: isPrimary is true. The first finger to touch the screen is the primary pointer. A drawing app can follow only the primary pointer and ignore a second finger.

The console prints touch, 7, and true.

Mouse events & buttons

INTERACTIVE

One click with the main mouse button is not one event. It is several events in a row. In most browsers, the order is:

  1. pointerdown: the button goes down.
  2. mousedown: the same press, sent again as a mouse event.
  3. pointerup: the button comes back up.
  4. mouseup: the same release, sent again as a mouse event.
  5. click: the press and the release together count as one click.

Buttons other than the main one send auxclick instead of click. "Aux" is short for auxiliary, which means "extra". The right button usually also sends contextmenu, which asks for the right-click menu. There is also dblclick, for a double-click. Use it only when the double-click itself matters.

The usual order of events in one clickPop out in the code editor (opens in a new tab)JavaScript
const lifecycle = [
  "pointerdown",
  "pointermove",
  "pointerup",
  "click",
];

console.log(lifecycle.join(" -> "));

This small program only prints the event names in order: pointerdown -> pointermove -> pointerup -> click. In a real click, the pointer may move many times between the press and the release, or not at all. The rule to remember: click comes after the button is released. So if a drag should start the moment the button goes down, listen for pointerdown, not click.

Most mice have three buttons. This lesson calls them the main button (usually the left one, also called primary), the middle button (usually the wheel, also called auxiliary), and the secondary button (usually the right one). Mouse and pointer events have two properties with almost the same name, and they answer different questions:

  • button answers "Which button changed in this event?" It is 0 for the main button, 1 for the middle button, and 2 for the secondary button.
  • buttons answers "Which buttons are held down right now?" Each button has its own number: 1 for the main button, 2 for the secondary button, and 4 for the middle button. JavaScript adds up the numbers of all held buttons. So 3 means 1 + 2: the main and secondary buttons are both down. A number built this way is called a bitmask.
Left: event.button is 2, the button that just changed. Right: event.buttons is 1 plus 2, which is 3: the primary and secondary buttons are both held.event.button2the button thatjust changedevent.buttons1+2=3primarysecondaryheldall buttons held now
The main button is held, then the secondary button is pressed. button is 2, the one that changed; buttons is 1 + 2 = 3, every button held now.

While the pointer moves, no button changes. So in mousemove and pointermove, buttons is usually the property you want.

Watch real pointer events
Show each property of the eventPop out in the code editor (opens in a new tab)JavaScript
pad.addEventListener("pointermove", (event) => {  show("pointerType", event.pointerType);  show("pointerId", event.pointerId);  show("isPrimary", event.isPrimary);  show("button", event.button);  show("buttons", event.buttons);  show("pressure", event.pressure);});
Live padbutton vs buttons
Move or press here
pointerType
move or press inside the pad
pointerId
—
isPrimary
—
button/buttons
—
client / offset
—
pressure
—
Legend: button: 0 main, 1 middle, 2 secondary. buttons: 1 main, 2 secondary, 4 middle, added together.
    Try it yourself

    Try the main, middle, and secondary mouse buttons on the pad. On a phone or tablet, touch it with a finger or a pen.

    The table shows the real browser event. A normal click usually logs pointerdown → mousedown → pointerup → mouseup → click. The secondary and middle buttons add events such as contextmenu or auxclick in most browsers.

    The pad uses React event handlers to show the values, but the event names and properties come from the browser. What you see for a pen or a finger depends on your device.

    To build your own right-click menu, listen for contextmenu, not only mousedown. Call preventDefault() in that listener to stop the browser's own menu. If you do, give keyboard users and screen-reader users another way to reach the same actions. The next lesson, Keyboard & focus, shows how.

    Step through button and buttons
    Step 0 of 6Ready
    Your turn: follow the blue line

    Pick a button, guess the two numbers, then step through the code.

    Running in
    1. script
    Next: line 1
      pointerType: "mouse",  pointerId: 1,  isPrimary: true,  button: 0,  buttons: 1,}; console.log(event.pointerType);console.log(event.button);console.log(event.buttons);
    CallStoreChangeResultBlue line: runs next. Ran: already executed.
    Recent returnsNothing yet. Start with the blue line.
    Pick which button is pressed

    Picking a new button starts the replay again.

    A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

    mouseover vs mouseenter

    INTERACTIVE

    Hover events fire when the pointer crosses the edge of an element. There are two pairs of them, and they behave differently:

    • mouseover and mouseout bubble. Bubbling means an event on a child element also reaches its parent. So when the pointer moves from one child to another inside a card, the card hears a new mouseover each time.
    • mouseenter and mouseleave do not bubble. The card hears mouseenter once when the pointer comes into the card, and mouseleave once when it goes out.
    Two copies of the same card, each holding a title and a button. Left: mouseover fires again on each child. Right: mouseenter fires once for the whole card.mouseovertitlebuttoncardfires againon each childmouseentertitlebuttoncardfires oncefor the whole card
    The pointer moves from the title to the button. mouseover bubbles, so the card hears it again; mouseenter fired once when the pointer came into the card.

    mouseover and mouseout also have a relatedTarget property. It is the other element in the move: where the pointer came from, or where it is going. That helps when one listener on a parent handles many children (event delegation). But for a card with an icon, a title, and a button inside, all those extra events are just noise.

    Real-life analogyA front-door bell and a bell in every room

    Picture a house with a bell at the front door and a small bell in every room. The front-door bell rings once when a visitor comes in. The room bells ring every time the visitor walks into another room. If you only care that someone came in, listen to the front-door bell. If you want to hear about every room, listen to the room bells.

    In real life: The front-door bell rings once when a visitor comes in
    In JavaScript: mouseenter fires once when the pointer enters the element
    In real life: A room bell rings each time the visitor walks into another room
    In JavaScript: mouseover fires again each time the pointer crosses into a child
    In real life: Asking which room the visitor just left
    In JavaScript: relatedTarget names the element the pointer came from
    Which hover events fire inside a card?
    One listener that bubbles, one that doesn'tPop out in the code editor (opens in a new tab)JavaScript
    const parent = document.querySelector(".card"); parent.addEventListener("mouseover", (event) => {  console.log("over", event.target.className);  console.log("from", event.relatedTarget?.className ?? "outside");}); parent.addEventListener("mouseenter", () => {  console.log("entered the whole card");});
    Nested cardmouseover 0 · mouseenter 0
    🏠Card title
      Try it yourself

      Move the pointer slowly over the emoji, the title, and the button inside the card.

      mouseover and mouseout bubble, so they fire again each time the pointer crosses into a child. mouseenter and mouseleave fire once, when the pointer enters or leaves the whole card.

      The log shows relatedTarget when the browser gives one. Coming in from outside the card often shows outside.

      Pointer events have the same two pairs:

      • pointerover and pointerout bubble, like mouseover and mouseout.
      • pointerenter and pointerleave do not bubble, like mouseenter and mouseleave.

      Use the mouse names when your code only cares about a mouse. Use the pointer names when the same widget must also work with a pen or a finger.

      Pointer events

      UNIVERSAL

      These are the pointer events:

      • pointerdown, pointermove, and pointerup: press, move, and release.
      • pointercancel: the browser stopped sending this pointer's events. You'll see why below.
      • pointerover, pointerout, pointerenter, and pointerleave: the hover pairs from the last section.

      They look like mouse events, but they carry extra properties about the device: pointerId, pointerType, isPrimary, pressure, and more.

      After most pointer events, the browser also sends the matching mouse event, such as mousedown after pointerdown. These extra events are called compatibility mouse events. They exist so that older code written only for a mouse still works. So don't run the same action in both a pointerdown listener and a mousedown listener: it would run twice. For drawing, sliders, resizing, and gestures, pick pointer events.

      When pointercancel appears

      pointercancel means the browser stopped sending this pointer's events to your code. It often happens on a touch screen, when the browser decides the finger is scrolling or zooming the page. On your own drag area, the CSS rule touch-action: none tells the browser: "my code handles touch gestures here, so don't scroll."

      Here is a common case. On a phone, a finger starts on your slider. Then it moves far enough that the browser thinks the user wants to scroll the page. The browser takes over, and your code gets pointercancel instead of pointerup. So clean up the drag in both cases, on pointerup and on pointercancel.

      Clean up when a gesture is canceledPop out in the code editor (opens in a new tab)JavaScript
      let dragging = true;
      
      function finishGesture(eventType) {
        dragging = false;
        console.log(eventType, dragging);
      }
      
      finishGesture("pointercancel");

      Line 1 says a drag is going on: dragging is true. The finishGesture function on lines 3 to 6 sets dragging back to false. You can call it for either ending event. Line 8 calls it for pointercancel, so the console prints pointercancel false. Without this cleanup, a canceled slider can stay stuck, still looking as if it is being dragged.

      When a control really needs the touch gesture for itself, add one CSS rule to it:

      Keep touch gestures for a custom sliderPop out in the code editor (opens in a new tab)CSS
      .custom-slider {
        touch-action: none;
      }

      The table below sums up the choices so far. Each row is one question your code might ask; read across to see what answers it.

      Which property or event to use for each job
      What do you need to know?What to useWhat it gives youWhen to pick it
      Which button changed?event.buttonA number: 0 main, 1 middle, 2 secondary.When a button goes down or up and you need to know which one.
      Which buttons are held now?event.buttonsA sum: 1 main, 2 secondary, 4 middle.During a move, to check that a button is still down.
      Did the pointer move from one child to another?mouseover / mouseoutThese events bubble and include relatedTarget.When one listener on a parent handles many children.
      Did the pointer enter or leave the whole element?mouseenter / mouseleaveThese events do not bubble.When moving between children should not start the hover again.
      What is any pointer doing?pointerdown / pointermove / pointerupThe same events for a mouse, a pen, and a finger, with pointerType.For drawing, sliders, resizing, and gestures.
      How do I move an item to a drop area?HTML drag and dropThe events dragstart, dragover, and drop, plus dataTransfer.For moving items with a mouse on a desktop. Touch support differs between devices.

      Pointer capture

      INTERACTIVE

      Dragging can break if the pointer has to stay exactly over the small thing you drag. Take a slider's thumb, the knob you drag. A fast hand can leave the thumb before the next move event arrives. Then the thumb stops getting moves, and it stops.

      Pointer capture fixes this. When you call thumb.setPointerCapture(event.pointerId), every later event from that pointer goes to the thumb, even when the pointer is somewhere else. Capture ends by itself after pointerup. You can also end it yourself with releasePointerCapture().

      Left: no capture. The pointer has moved off the thumb, its moves go elsewhere, and the thumb stops. Right: after setPointerCapture(), an arrow shows the pointer's moves still going to the thumb, so the thumb follows.no capturethumbpointermoves miss the thumbthumb stopssetPointerCapture()thumbpointermoves still reach itthumb follows
      In both halves the pointer has moved off the thumb. With capture, that pointer's moves still go to the thumb, so the drag keeps working.
      Real-life analogyPointer capture is holding a kite string

      When you fly a kite, the kite can drift far away from you, but the string still ties it to your hand. Pointer capture ties the pointer to the thumb in the same way. The pointer can move away, and the thumb still gets its events until you let go.

      In real life: Your hand holds the string
      In JavaScript: The element keeps getting that pointer’s events
      In real life: The kite flies far from your hand
      In JavaScript: The pointer moves outside the element
      In real life: You let go of the string
      In JavaScript: pointerup or releasePointerCapture() ends the capture
      Drag a slider with and without capture
      Capture the pointerPop out in the code editor (opens in a new tab)JavaScript
      thumb.addEventListener("pointerdown", (event) => {  thumb.setPointerCapture(event.pointerId);  drag(event.clientX);}); thumb.addEventListener("pointermove", (event) => {  if (event.buttons === 1) drag(event.clientX);}); thumb.addEventListener("pointerup", (event) => {  thumb.releasePointerCapture(event.pointerId);});
      Custom slider35%
        Try it yourself

        Capture is on. The thumb keeps getting this pointer's moves until pointerup, even when you drag outside the thumb.

        The slider has touch-action: none, so a finger drag moves the slider instead of scrolling the page.
        Capture on press, move while held, release at the endPop out in the code editor (opens in a new tab)JavaScript
        thumb.addEventListener("pointerdown", (event) => {  thumb.setPointerCapture(event.pointerId);  drag(event.clientX);}); thumb.addEventListener("pointermove", (event) => {  if (event.buttons === 1) drag(event.clientX);}); thumb.addEventListener("pointerup", (event) => {  thumb.releasePointerCapture(event.pointerId);});

        Line 2 starts the capture when the button goes down. Line 7 moves the thumb only while the main button is held (buttons === 1). Line 11 ends the capture when the button comes up.

        A card that keeps getting its pointer’s eventsPop out in the code editor (opens in a new tab)JavaScript
        card.addEventListener("pointerdown", (event) => {  card.setPointerCapture(event.pointerId);  card.classList.add("dragging");}); card.addEventListener("pointerup", (event) => {  card.releasePointerCapture(event.pointerId);  card.classList.remove("dragging");});

        Line 2 captures the pointer when the press starts, so the drag keeps working outside the card. Line 3 adds the dragging class, which only changes how the card looks. A real app would also move the card in a pointermove listener. Line 7 releases the capture when the press ends. Always release capture when the gesture ends or is canceled.

        Drag and drop

        INTERACTIVE

        HTML drag and drop is a different set of events. It moves data from the item you drag (the source) to the place you drop it (the target). It takes four steps:

        1. Mark the source as draggable: draggable="true" in HTML, or card.draggable = true in JavaScript.
        2. In the source's dragstart listener, save some data with event.dataTransfer.setData(). dataTransfer is the object that carries data during a drag.
        3. In the target's dragover listener, call preventDefault(). This tells the browser the target accepts drops. Many apps do the same in dragenter.
        4. In the target's drop listener, read the data with getData() and move the item.

        While the drag is going on, the browser protects the data so that other code can't read it. That is why you can read your data in drop, but not in dragover.

        Three steps in order. 1: dragstart saves the card's id with setData(). 2: dragover calls preventDefault() to accept the drop. 3: drop reads the id with getData().dragstartdragoverdrop1. save the idsetData()2. accept the droppreventDefault()3. read the idgetData()
        The id is saved when the drag starts and read when it drops. In between, the target must call preventDefault() or the drop never happens.
        Real-life analogyDrag and drop is a moving company

        Movers won't leave a box at a house unless someone there says "yes, deliver it here." A drop target is the same: it must say yes. It says yes by calling preventDefault() in dragover. This is the step people forget most often.

        In real life: The movers pack a box
        In JavaScript: dragstart saves the card’s id with dataTransfer.setData()
        In real life: The new home says “yes, deliver here”
        In JavaScript: dragover calls preventDefault() to accept the drop
        In real life: The movers unpack the box
        In JavaScript: drop reads the id and moves the element
        In real life: The movers finish the job
        In JavaScript: dragend cleans up the look, whether the drop worked or not
        Drag cards between two lists
        Accept the drop in dragoverPop out in the code editor (opens in a new tab)JavaScript
        card.draggable = true; card.addEventListener("dragstart", (event) => {  event.dataTransfer.setData("text/plain", card.id);}); target.addEventListener("dragover", (event) => {  event.preventDefault();}); target.addEventListener("drop", (event) => {  const id = event.dataTransfer.getData("text/plain");  target.append(document.getElementById(id));});
        Two listsHTML drag and drop
        Try it yourself

        Use a mouse or a trackpad. Many touch screens don't run HTML drag and drop the same way.

        Drag a card to another list.

        The lists are built with plain DOM methods inside an empty container. That way React doesn't try to manage elements that the browser moves during the drag.
        The four steps of drag and dropPop out in the code editor (opens in a new tab)JavaScript
        card.draggable = true; card.addEventListener("dragstart", (event) => {  event.dataTransfer.setData("text/plain", card.id);}); target.addEventListener("dragover", (event) => {  event.preventDefault();}); target.addEventListener("drop", (event) => {  const id = event.dataTransfer.getData("text/plain");  target.append(document.getElementById(id));});

        Line 1 makes the card draggable. Line 4 saves the card's id when the drag starts. Line 8 accepts the drop on the target. Lines 12 and 13 read the id and move the card into the target.

        Where you’ll use this

        PRACTICAL

        Real apps often mix these events:

        • A drawing app uses pointer events, so it works with a mouse, a pen, and a finger.
        • A splitter, the bar you drag to resize two panels, captures the pointer. It keeps resizing even when your hand moves faster than the bar.
        • A file manager might use HTML drag and drop on a desktop, and pointer events on touch screens.
        Draw or resize with pointer eventsPop out in the code editor (opens in a new tab)JavaScript
        element.addEventListener("pointerdown", (event) => {  if (event.button !== 0) return;  element.setPointerCapture(event.pointerId);}); element.addEventListener("pointermove", (event) => {  if (event.buttons !== 1) return;  drawLineTo(event.clientX, event.clientY);});

        Line 2 ignores any press that is not the main button (button is not 0). Line 3 captures the pointer. Line 7 skips moves when the main button is not held. Line 8 draws to the pointer's position.

        Draw lines on a canvasPop out in the code editor (opens in a new tab)JavaScript
        const canvas = document.querySelector("canvas");const context = canvas.getContext("2d"); canvas.addEventListener("pointerdown", (event) => {  context.beginPath();  context.moveTo(event.offsetX, event.offsetY);}); canvas.addEventListener("pointermove", (event) => {  if (event.buttons !== 1) return;  context.lineTo(event.offsetX, event.offsetY);  context.stroke();});

        A <canvas> is an HTML element that JavaScript can draw on. This code works the same for a finger, a mouse, or a pen:

        • Lines 4 to 7: pointerdown starts a new line at the pointer's spot.
        • Lines 9 to 13: pointermove adds to the line, but only while the main button is held (line 10).
        • The page's CSS gives the canvas touch-action: none, so a finger draws instead of scrolling the page.

        A full version would also listen for pointerup and pointercancel to end the line.

        Which event should this feature use?
        • Highlight a menu once when the pointer enters it, even though the menu holds icons
        • Draw with a mouse, a finger, or a pen
        • Move cards between lists, with the browser showing where they can drop
        • Open your own right-click menu
        • Make a brush line thicker when a pen presses harder
        • Let a card carry its id to a drop area
        • Show a tooltip once when the pointer enters a button that holds an icon
        • Run a special action when the middle button (the wheel) is clicked
        Try it yourself
        0 of 8 correct

        Put each feature in the group of events it needs most.

        Choose a category for every card. You can change an answer at any time; Reset clears them all.

        Common misconceptions

        • "Pointer events are the CSS pointer-events property." No. Pointer events are JavaScript events, such as pointerdown. The CSS property pointer-events is something else: it decides whether an element can be clicked or hovered at all.
        • "button and buttons mean the same thing." No. button is the one button that changed. buttons adds up every button held right now.
        • "mouseenter bubbles like mouseover." It does not. A parent does not hear mouseenter from its children. If one listener on a parent should handle many children, use mouseover.
        • "Pointer capture captures every pointer." No. It captures one pointer, chosen by its pointerId, for one element.
        • "HTML drag and drop works the same on every touch screen." No. Touch support differs between devices. Test on real phones, and think about using pointer events for touch dragging.
        • "A drop listener is enough." No. The browser normally fires drop only on a target that called preventDefault() during dragover.

        Practice exercises

        5 EXERCISES
        Exercise 1 · Warm-upRead the button numbers
        What two lines does the console print?
        Starter codePop out in the code editor (opens in a new tab)JavaScript
        const button = 2;
        const buttons = 3;
        console.log(button);
        console.log(buttons);

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 2 · Warm-upChoose the hover event that fires once
          A card holds an icon, a title, and a button. Which event fires once when the pointer enters the card, and not again when it moves between those children?

          Answer, then press Check. Spacing and letter case don’t matter.

            Exercise 3 · PracticeAccept a drop
            A drop target must call preventDefault() in dragover to accept drops. This small program pretends to do that step. What does it print?
            Starter codePop out in the code editor (opens in a new tab)JavaScript
            let canDrop = false;
            const event = { preventDefault() { canDrop = true; } };
            event.preventDefault();
            console.log(canDrop);

            Answer, then press Check. Spacing and letter case don’t matter.

              Exercise 4 · PracticeFix the slider that loses the pointer
              A custom slider stops moving when the pointer leaves its thumb. Which method should the thumb's pointerdown listener call?

              Answer, then press Check. Spacing and letter case don’t matter.

                Exercise 5 · ChallengeTurn a pointer position into a percent
                clientX is the pointer's distance in pixels from the left edge of the window. A slider track starts at clientX 100 and is 200 pixels wide. The pointer is at clientX 175. What percent does the program print?
                Starter codePop out in the code editor (opens in a new tab)JavaScript
                function percent(clientX, left, width) {
                  const raw = ((clientX - left) / width) * 100;
                  return Math.max(0, Math.min(100, Math.round(raw)));
                }
                console.log(percent(175, 100, 200));

                Answer, then press Check. Spacing and letter case don’t matter.

                  Check your understanding

                  7 QUESTIONS
                  Mouse, pointer & touch quiz · 7 questionsScore: first tries count
                  1. Question 1 of 7In most browsers, which is true for a normal click with the main mouse button?

                    Choose an answer to see the explanation.

                  2. Question 2 of 7What does this print?

                    Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                    const event = { button: 1, buttons: 4 };
                    console.log(event.button);
                    console.log(event.buttons);

                    Choose an answer to see the explanation.

                  3. Question 3 of 7Why can mouseover fire several times while the pointer stays inside one card?

                    Choose an answer to see the explanation.

                  4. Question 4 of 7What should you set on a custom touch slider so the browser does not take over the drag to scroll the page?

                    Choose an answer to see the explanation.

                  5. Question 5 of 7This program pretends to be a dragover listener. What does it print?

                    Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                    let allowed = false;
                    const event = { preventDefault() { allowed = true; } };
                    event.preventDefault();
                    console.log(allowed);

                    Choose an answer to see the explanation.

                  6. Question 6 of 7When can dataTransfer.getData() read your own drag data?

                    Choose an answer to see the explanation.

                  7. Question 7 of 7Which event should you listen for to build your own right-click menu?

                    Choose an answer to see the explanation.

                  Key takeaways

                  • Mouse events still matter for clicks, hover, other-button clicks (auxclick), and right-click menus (contextmenu).
                  • button says which button changed. buttons says which buttons are held now.
                  • mouseover and mouseout bubble. mouseenter and mouseleave do not.
                  • Pick pointer events for custom controls that must work with a mouse, a pen, and a finger.
                  • Pointer capture sends one pointer's events to one element for the whole drag.
                  • HTML drag and drop needs preventDefault() in dragover, and it works differently on touch screens.

                  Final definition: Pointer events are browser events about one mouse, pen, or touch point. They use the same set of events for every device.

                  Up next: Keyboard & focus.

                  CompleteFrontend Clear concepts. Working examples.