There are three general event types of interest when working something out with mouse events that are on mouse down, on mouse move, and on mouse up. There are other events of interest, such as mouse out and mouse over events, but for the most part I only bother with those first three events when working out any kind of user interface that will make use of a mouse if present.
Mouse events are not always the best way to go about making a truly universal input controller type module, or any kind of component of an application that has to do with user input, at least not by them selfs anyway. There are of course also touch events, and keyboard events that should be taken into consideration also when working on something to that effect. So then when it comes to working out an interface that will work with pointer devices in general it might be better to start out with pointer events actually. Pointer events are as the same suggests about pointers in general not just in terms of a mouse, but touch and pen devices also. There is then only bothering with mouse and touch events when it comes to making separate user interfaces for desktop and mobile devices.
However mouse events work great when it comes to attaching events that will allow for a great deal of control over what will happen for traditional desktop clients. When doing so it is impotent to be aware of how browsers simulate mouse events for touch scripts, and how to prevent that default behavior. It should also go without saying that one should also use touch events, and or pointer events as a fall back for mouse events to make a user interface work with all clients that will visit a page. In any case in this post I will be covering a great deal about mouse events, but also pointer events in general while I am at it.
The main element object and nice method to be aware of when it comes to attaching mouse events and events in general is the add event listener method. Each time I call the add event listener method I pass a string value for the desired event type I want to attach for, and then a function that will fire each time the event fires. Inside the body of this function I will have access to an event object that contains useful info about the event. For mouse events this event object contains information about where in the browser window the event happened, the mouse button that was clicked of any, and a reference to an element where it happened to name just a few features of interest with these event objects.
- The source code examples in this post are on github
1.1 - The window on click event
For this example I am just setting a simple count variable and setting the inner text of a div element that I have gained a reference to by way of the document.getElementById method.
Using the on click property of the window object, or any other node such as an element, can be thought of as the old, tired yet true way of doing this sort of thing. If for some reason you want to get your code to work on what are now very old web browsers you would want to do something like this. However for the most part I find myself just using the add event listener method as the method is well supported these days.
1.2 - Using addEventListener to attach an event to window
A more modern way of attaching event listeners to the window object, as well as nodes in general including elements would be to use the add event listener method. One major improvement with this is that it can be used as a way to attach more than one hander. Although it may not be one of the oldest ways of going about performing event attachment, at this point it is only fairly old browsers that will result in code breaking changes.
Once again I am just stepping a count variable in the body of one event handler, but in this event handler I am using the style API as a way to change a CSS value for the div rather than just setting the value of a text node.
For this example I am just using the style api to change the background color of a div, but it can also be used to change any css value such as the left and top properties when using an absolute positioned div.
1.3 - The mouse down, up, move events, and event objects
On top of the click event there are also a number of other mouse events such as the mousedown event that will fire the very moment that a mouse button is clicked, and the mouseup button that will fire once a mouse button is released. There is also the mouse move method that will fire each time the mouse pointer location changes.
On top of the additional events beyond that of just the click event there is also the event object that is passed to a handler that contains a fair amount of data about the mouse event. For this example then I will be using the client x and client y properties to find the window relative position of the mouse cursor when these events happen.
In this example I am adding a state object that will be used to store an x and y value as well as a down boolean value. I then aim to mutate this state object’s values with mouse events, and update a view for this state object each time an event happens.
When this example is up and running in the browser I end up with the current values of the state object being displayed. Moving the mouse around will result in the position being updated, and clicking the mouse button will change the value of the down boolean value.
1.4 - parent and child divs
Now for an example where I am starting to get into the whole parent and child element thing with mouse events. For this example I have a single parent div, and I am creating and injecting a whole bunch of child elements into this parent element. This time around I am attaching just a single event handler to the parent element, and I am using the target and current target properties of the event object to find out if I am dealing with a child element or not.
In the event that I am dealing with a child element that was clicked I am giving just the child a new random position, else if I am clicking the parent element then I set new random positions for all the children of the parent element. So then this is just another example of what there is to work with when it comes to event objects in mouse events. I can get a window relative position, and I can get references to elements.
2 - Get element relative position
So one thing that might come up right away is that the position that is obtained from the clientX, and clientY properties might not always be what one might expect. The values are always going to be relative to the start of the browser window rather than an element in that window. So then there is a need to find a way to get a position that is relative to a specific element, rather than that of the window.
One way to go about resolving the issue of the position not being relative to an element rather than the window the get bounding client rect method of the target element of the event object can be used to get the position of the element in the window. These values can then be used to get a position that is relative to the element rather than the whole window by subtracting values in the object that is returned from the clientX, and clientY values.
There may be additional ways of going about getting an element relative position, and also a whole bunch of other things that might come up when it comes to all kinds of related tasks that will branch off from this such as making methods that will work not just with mouse events but pointer events in general. So then in this section I will be getting into some basic examples, and then maybe some not so basic examples of making a system to get element relative positions from event objects of mouse and pointer event handlers.
2.1 - Basic get element relative position example
For this example I am attaching an event handler to a div element, and using the inner html property as a way to create, and recreate a child div each time the parent div is clicked. For this example I am making sure to use the current target property rather than the target property to get a reference to the parent element. The reason why is because the target property might end up referring to the child element that I am creating for the inner html value of the parent element.
2.2 - Method to get an element relative position for mouse and touch events
Working out how to get an element rather than window relative mouse cursor position is one thing, but often I will want to get such a position for touch events also. So then there is often a need to have some kind of simple helper method that will return an object with adjusted x and y values from a given event object from a mouse or touch event. If the event object is a mouse event I can just use clientX, and clientY, but if the event object is a touch event that makes things a little more involved. One major reason why is because when it comes to touch devices there is of course multi touch. So With a touch event I have to think more in terms of an array of objects where each object contains a clientX, and clientY value.
2.3 - Canvas element example with mouse and touch events
One more example now, this time I am getting the get element relative method to work well with canvas elements also. This will often require just one little adjustment that has to do with a weird issue when it comes to the scaled size of a canvas relative to the actual native size of the canvas. Aside from that the method seems to work well with canvas elements also when I made just one little revision to the source code of the get element relative method.
This time I went with attaching the events to a canvas element that is the nested element of interest. I could leave the events attached to the window object, but that would result in the events continuing to fire even when I do something with the mouse outside of the canvas element.
3 - The onclick mouse and touch event
The on click event can be thought of as a mouse event in the sense that the name is click rather than touch. However the on click event is actually an event that will fire for both mouse and touch events. This might not always be a problem if this is of course the behavior that you want when making an interface, however if I am making an interface where I want separate logic to fire for mouse events from that of touch events then it is a problem.
3.1 - A basic on click event example
To start off with this section I am going to just have a very basic example of the on click event. For this one I just quickly put together a quick example that involves just using the click event with a div element and making it so that clicking the div element will toggle the background color by way of the style api.
One major thing about the click event is that on systems that support both a mouse, as well as a touch screen the click event will fire for both a mouse click as well as a touch of the touch screen surface. In many cases in which I use the on click event this is not a problem as that is the kind of behavior that I want. However in some cases this is not what I want to happen, and I want to have separate code that will run just for a mouse click, and just for a touch “click” if I can call it such for a moment. So now that I have a basic example of the on click event out of the way I should now get into at least a few more examples that have to do with the click event and I kind of virtue click event.
3.2 - The type and pointerType properties of a click event
If I want to find out if I am dealing with a mouse click or a touch “click” if it can be called such, one way to do so would be to use the pointerType property of the event object for the click event handler. This should not be confused with the type property of the event object as that is the type of event which in this case is a click event.
So then the pointerType property is a good way to go about finding out if I am dealing with a mouse or a touch event when making an event handler that will be used with the click event.
3.3 - Prevent default and mousedown and touchstart events
The pointerType event is useful when it comes to finding out if I am dealing with a mouse or touch event in a click event. However sometimes I need to make some kind of system where I need to attach events for mouse down and touch start events, along with maybe additional events. The default behavior with this kind of situation is that the touch start event will fire first, and then a mouse down event will fire. If for some reason I do not want this to happen the prevent default method would seem to work okay to suppress this.
3.4 - Input elements and the on click event
So there is attaching a client event to the window object, but there is also attaching events to various other kinds of elements such as an input element. For this example I am attaching an event handler to an input element that is a button type input element. When it comes to input elements it is often the value property of the input element that is of interest. When it comes to button input elements the value property is the display value of the button. So in this example I am attaching an event handler to an input element that will update the display value of the button each time it is clicked with the value of a count variable.
In this example I am using the target property of the event object to get a reference to the button that was clicked rather than by some other means. One reason why is because I am making my event handler a stand alone function and then passing a reference to that function for more than one call of the add event listener method. Inside the body of an event handler the target property will be a reference to the element where the event has happened. There is also the current target property that is the current element to which the event element is firing, but that is something that I will be getting more into in a later example.
In this example I am also using the parseInt method as a way to make sure what might be a string value of a number is converted to a number. I am also making use of html data attributes as a way to store a count value for each element.
3.5 - Simulate a on click event
While I am at it I think I should have at least one example in this section that involves simulating a click event. For this kind of thing there is a click method of an element object reference that can be called as a way to simulate a click event. So then for this example I am using that method as a way to do so. So then in this example there is clicking one of the input elements to step a count value in the data attribute of the input element, and also the event of doing so is being simulated in a function that is being called every second thanks to the setInterval method.
4 - Mouse buttons
There are a few things to be aware of when it comes to mouse buttons when working with mouse events, and also taking into account accessibility with touch events still. For example there is often both a left and right click mouse button, but there is also a center click as well as a scroll wheel of a mouse typicality. Also there may be a few more buttons on a mouse such as a back and forward button, and even more buttons in some cases.
However there is also the fact that a lot of people that visit a web application might be using the application from a touch screen. So for example there should also be ways of simulating a right click, or at least giving a way to do the same action as a right click.
4.1 - Basic mouse buttons example
The value of the button property should be a number with a value from 0 to 4 for up to five buttons on a mouse that was pressed. A value of 0 should mean the left click button of the mouse, while a value of 2 on the other hand will be a right click actually. So then a value of 1 will refer to a center click, or scroll wheel click if you prefer. The values of 3 and 4 will refer to the back and forward buttons that are present on many mouses these days. That is about it as far as I know, it might be possible to find a way to work with even more buttons that might be on some kinds of mice that people might use, however there is mainly thinning just in terms of what there is to work with for most people using desktop systems. When it comes to using the track pad of a laptop often there is only a right and left click and that is all.
4.2 - Stop the context menu from showing up on a right click
There is one thing to be aware of when it comes to the subject of mouse events and right clicking and that is of course the context menu. By default when I right click a web page in a web browser I get a context menu that gives me some options such as viewing the source code of the web page, or saving an image in the page as a file on my local file system. That is all fine and good, but in some cases I might not want that to happen for a web application so there should be a way to stop the context menu from showing up.
The way that I have found to do this is to not just make use of the mouse down and touch start events, but also the on context menu event. The main thing to do in a handler for this on context event is to call the prevent default method, however there are some additional things that I might also want to do on top of that when it comes to how things work on various other browsers.
There might be even more to write about when it comes to additional logic that will define what to do for a application when the user right clicks a location on a canvas, or use one of the other buttons that there may be there to work with. However that of course will depend on the application that is being used.
5 - Get elements by mouse position
When it comes to getting one or more elements from a mouse position there are a range of ways of going about doing so. When it comes to events such as the click event there is just using the target property of the event object. However things might prove to be a little more involved when I just want to get the top most element from a given window relative position, or get not just one element but all elements that might overlap at a given point. So then in this section I thought I would go over a few examples that have to do with getting one or more element references from a given window relative position or point if you prefer.
5.1 - Just using the on click event and the target property of the event object
As I have mentioned in previous examples the target property of an event object is the original element at which an event has happened. So then one way of going about getting an element by way of a window relative position would be to just attach a click event to the window object and then just look at the target property of the event object.
5.2 - The Document.elementFromPoint method
Another tool in the tool box that has to do with getting an element reference by way of a window relative point would be to use the document.elementFromPoint method to do so. This method can just be called from anywhere and then I just need to pass the x and y value at which I would like to get the top most element at that location.
One drawback of this solution as well as with the basic one that I started this section off with is that I can not get more than one element that may be at the same location all the way down to the body element. In that kind of situation I would need to make some kind of solution that involves filtering through all the elements performing bounding box collection for each maybe.
5.3 - Get all elements at a position
There is also a document method that can be used to get all elements at a given window relative position. So just like that of the document get element from point method, there is also a document get elements from point method. One cool thing about this method is that it will return a plain old array when it comes to the collection of elements that are found overlapping at the given point. It is then just a matter of looping over the nodes and doing whatever is necessary to filter, or perform some checks to make sure that I am just performing a desired action with the nodes that I actually want to work with at the given point in the browser window.
6 - The mouse wheel
On top of that of buttons a mouse often has a scroll wheel also, and with that said yes there is a wheel event than can be used to attach some logic that will run each time the mouse wheel moves. So then I have started this section as a place to park at least one if not more examples making use of this event as a way to do something with the mouse wheel.
6.1 - Basic mouse wheel example
Like always I have to start out a section like this with a kind of hello world style example so then here it is. To make use of this event I just need to use the add event listener method and attach for the wheel event. Inside the body of the event handler there is the deltaY value that can be used to apply as a delta value for a variable.
6.2 - Disabling scrolling in a mouse wheel event
One will want to take care when trying to disable page scrolling when using mouse wheel events. Thinking from a user experience perspective for a moment I would not want to disabled page scrolling by way of a mouse wheel for the page as a whole, at least nit in mouse use case examples of the mouse wheel event. However I would often want to disable it when the user hovers their mouse over a canvas element, division, or any other kind of element to which I am attaching an event hander for the mouse wheel event.
I have run into problems when it comes to trying to disable page scrolling my way of a hander that is attached to the window object. However when it comes to attaching a hander to an element, and just using the prevent default method in the handler that seems to produce a desired end result.
6.3 - Full screen trick using css
So then there is the idea of having a way to switch between a full screen mode of sorts as well as a window mode. What makes things a little involved is that when I switch to full screen mode I can do something like set a container div to absolute, or fixed positing and adjust the width and hight of the container. However when doing so the page content will still case scroll bars to appear on the side of the browser window. If I just care about the mouse wheel and that is all then maybe this is not a problem, but when it comes to taking into account other ways of scrolling and so forth I should have a way to disable the page content when the container div is in this full screen mode of sorts.
There may be a number of ways of gong about setting up the kind of system that I have in mind for having a mouse wheel event and various other events attached to a container div that is can then be changed by some kind of action made by the user. That is that having the mouse wheel event work the way that I want it to when the container is in window mode as well as full screen mode, and for the content of the page to not be displayed when the container is in full screen mode. However for this example at least I am going to just start out with something fairly simple that might prove to just be a decent starting point for this sort of thing, by just using a little CSS.
So then this is the basic idea that I more or less have in mind that seems to work okay thus far. Now there is just the question of how to go about making this into something that will work in any page. Such a solution might have to involve a fair amount of code to run threw the page content setting the display css prop of all page content to none, accept for of course the container div. Then it would have to set all of the display properties back to what they where when it comes to going back to the window mode. However there might prove to be another solution that is less complex, and well supported in browsers these days, such an option might be to look into the full screen API.
7 - Pointer events to work with mouse and touch events
One downside of using these events is that I will not have access to the widest range of values and features to work with compared to the mouse events when it comes to things like what button was clicked and so forth. Also when it comes to touch events I do not see touch arrays in the event objects, so I can not do anything with multi touch. However most of the time when I make a project that will use the mouse and also work with touch devices I do not really do much if anything with these advanced features to work with actually so these pointer events more often than not will work fine.
7.1 - Basic pointer event example using the pointer down event
For this example I am starting this section off with an example where I am just attaching a pointer down event to the window object. This is an event that will fire whenever a pointer device will be in what is called active buttons state. This active button state is a state in which a mouse button on a mouse is pressed down, or when a touch screen is touched by one or more digits.
So when I open up this example in my browser the count will step when I left client the div, but also when I click any other button also. When it comes to using a touch device to touch a div that two seems to work as expected by causing the count to step forward.
7.2 - Pointer id and type
There is then the pointer id and the type of the pointer in the event object that will often be of interest when it comes to working with these kinds of events.
7.3 - On pointer move event and the touch action css property
The pointer move event then works just fine when it comes to using a mouse as I get more or less the same effect as I have come to expect from the mouse move event. However when it comes to using the pointer move event for the first time you might run into a problem compared to the touch move event when the pointer device is a touch device rather than a mouse. One way to address this problem would be to use the touch action css property and be sure to set it to none for the node that one is attaching to for the pointer move event.
8 - Simulation of mouse events
8.1 - basic example just using the client method
For this example I just have an event handler attached to the window object that will step a count when clicked. I am then just calling the click method off of the body element by way of the reference attached to the document object.
8.2 - Using the dispatch event method
For this example I am using the dispatch event method rather than just the click method. In order to use the dispatch event method I must have an event object to pass as an argument n for the method. So then I first need to create an event object, and set the properties that I want for the object.
8.3 - Simulating a mouse move event
If I can simulate a click event, and also set a position as to where the click happened then I should be able to do the same for other mouse events such as a mouse move event also. With that said in this example I am looking into simulating a mouse move event, to do so I just need to change a few tings with the same code that I worked out for simulating a click. The event name that I need to give to the Mose Event constructor is just mousemove rather than click, I then need to set up at least one event hander for a mouse move event rather than just for the click event, and that is about it.
With this example I also took a moment to use the style api to change the position of a fixed position div that is also updated in the body of the event hander that I am attaching for a mouse move event. I also added a loop that makes used of the setTimeout method to call my simulate mouse helper over and over again in a loop function. The result is then a circular motion being simulated with the mouse move event.
9 - Using both mouse and touch events rather than pointer events
Using pointer events might be great as a starting point for user interface design, however often I might want to make a user interface where there is logic that will work just for mouse events, and then completely separate logic for touch events. For example I might want to work out a whole lot of code that will work well with multi touch, and then other code that will make use of mouse features such as a right click button. So then in this section I will be exploring how to go about getting started with this kind of system when it comes to working with a mouse, as well as touch events in a client side web application.
9.1 - A starting point using touch start and mouse down events
For this example I am starting out with a system that uses touch start events to create an object pool by way of multi touch. That is that when I touch the screen I will get an object for each touch point on the surface of the canvas. In the event of a mouse down event I will create a new pool with just one object, but only for a mouse down event in which the left click button is pressed. Allowing me to use center and right click events to push as many objects as I want to the pool.
10 - Conclusion
When it comes to working out some kind of project that will work as something that will parse input from an array or sources I made a canvas example post that is an input controller of sorts. This canvas example is one of many such canvas examples that I am working on a little now and then that serve as real projects examples of sorts. So for more on mouse events as well as many other related topics you might want to check that post out.