Skip to content Skip to sidebar Skip to footer

Javascript Function on Click and Click Again

The click event is quite simple and easy to use; you lot listen for the result and run code when the event is fired. It works on just about every HTML element there is, a core feature of the DOM API.

Equally oft the case with the DOM and JavaScript, in that location are nuances to consider. Some nuances with the click event are typically non much a concern. They are pocket-size and probably virtually people would never even notice them in the majority of use cases.

Accept, for instance, the click consequence listening to the grandfather of interactive elements, the <button> chemical element. There are nuances associated with push button clicks and these nuances, like the divergence betwixt a "click" from a mouse pointer and "click" from the keyboard. Seen this fashion, a click is not always a "click" the manner it's typically divers. I actually accept run into situations (though not many) where distinguishing between those two types of clicks comes in handy.

How practise we distinguish between different types of clicks? That'southward what we're diving into!

First things first

The <push> element, equally described by MDN, is simply:

The HTML element represents a clickable button, used to submit forms or anywhere in a document for accessible, standard button functionality. By default, HTML buttons are presented in a fashion resembling the platform the user amanuensis runs on, but you can change buttons' advent with CSS.

The part we'll cover is obviously the "anywhere in a certificate for accessible, standard button functionality" office of that description. As you may know, a button element can have native functionality inside a grade, for example it can submit a grade in some situations. Nosotros are only really concerning ourselves over the bones clicking role of the element. So consider just a unproblematic push placed on the folio for specific functionality when someone interacts with it.

Consider that I said "interacts with it" instead of simply clicking it. For historical and usability reasons, one can "click" the button past putting focus on information technology with tabbing and and then using the Space or Enter key on the keyboard. This is a chip of overlap with keyboard navigation and accessibility; this native characteristic existed way before accessibility was a business. Yet the legacy feature does assistance a great deal with accessibility for obvious reasons.

In the example above, you can click the push button and its text label will alter. Afterwards a moment the original text will reset. You tin also click somewhere else within the pen, tab to put focus on the button, and and then employ Space or Enter to "click" it. The same text appears and resets as well. There is no JavaScript to handle the keyboard functionality; information technology'southward a native characteristic of the browser. Fundamentally, in this example the button is merely aware of the click event, but not how it happened.

One interesting difference to consider is the behavior of a push button beyond different browsers, specially the way it is styled. The buttons in these examples are set to shift colors on its active country; and then yous click it and it turns purple. Consider this prototype that shows the states when interacting with the keyboard.

Keyboard Interaction States

The start is the static country, the 2d is when the push has focus from a keyboard tabbing onto it, the third is the keyboard interaction, and the fourth is the result of the interaction. With Firefox yous will but see the kickoff two and last states; when interacting with either Enter or Space keys to "click" it you lot exercise not run into the tertiary state. Information technology stays with the 2nd, or "focused", state during the interaction and and so shifts to the last 1. The text changes as expected but the colors do not. Chrome gives the states a bit more as you'll see the first 2 states the same equally Firefox. If you lot employ the Space key to "click" the button you'll run into the third state with the color change and and then the final. Interestingly plenty, with Chrome if y'all use Enter to interact with the button you won't see the third state with the colour change, much like Firefox. In case you are curious, Safari behaves the aforementioned as Chrome.

The code for the outcome listener is quite simple:

          const button = document.querySelector('#push button');  push.addEventListener('click', () => {   button.innerText = 'Push Clicked!';      window.setTimeout(() => {     button.innerText = '"click" me';   }, 2000); });        

Now, let's consider something here with this code. What if y'all found yourself in a situation where you wanted to know what caused the "click" to happen? The click event is usually tied to a pointer device, typically the mouse, and withal here the Space or Enter key are triggering the aforementioned event. Other grade elements have similar functionality depending on context, but any elements that are not interactive by default would crave an additional keyboard event to work. The push button element doesn't require this additional event listener.

I won't become besides far into reasons for wanting to know what triggered the click event. I can say that I accept occasionally ran into situations where information technology was helpful to know. Sometimes for styling reasons, sometimes accessibility, and sometimes for specific functionality. Oft different context or situations provide for dissimilar reasons.

Consider the following not as The Way™ but more of an exploration of these nuances we're talking about. We'll explore handling the various ways to interact with a button element, the events generated, and leveraging specific features of these events. Hopefully the following examples can provide some helpful data from the events; or possibly spread out to other HTML elements, equally needed.

Which is which?

Ane uncomplicated way to know a keyboard versus mouse click effect is leveraging the keyup and mouseup events, taking the click outcome out of the equation.

Now, when you use the mouse or the keyboard, the changed text reflects which event is which. The keyboard version will even inform y'all of a Infinite versus Enter key existence used.

Here's the new code:

          const button = document.querySelector('#button');  function reset () {   window.setTimeout(() => {     button.innerText = '"click" me';   }, 2000); }  push.addEventListener('mouseup', (e) => {   if (e.push button === 0) {     button.innerText = 'MouseUp Issue!';     reset();   } });  button.addEventListener('keyup', (e) => {   if (due east.lawmaking === 'Infinite' || eastward.code === 'Enter') {     push button.innerText = `KeyUp Event: ${e.code}`;     reset();   } });        

A chip verbose, true, but we'll become to a slight refactor in a bit. This instance gets the point across about a nuance that needs to be handled. The mouseup and keyup events have their own features to account for in this situation.

With the mouseup event, most every button on the mouse could trigger this event. We normally wouldn't want the right mouse button triggering a "click" consequence on the button, for case. So we wait for the due east.button with the value of 0 to identify the primary mouse push. That way it works the same as with the click upshot yet we know for a fact it was the mouse.

With the keyup event, the same matter happens where about every key on the keyboard will trigger this event. So nosotros await at the event'due south code property to wait for the Space or Enter key to exist pressed. So at present it works the aforementioned as the click outcome just we know the keyboard was used. We even know which of the two keys we're expecting to piece of work on the button.

Another take to determine which is which

While the previous case works, it seems like a bit also much code for such a simple concept. Nosotros actually just want to know if the "click" came from a mouse or a keyboard. In most cases we probably wouldn't care if the source of the click was either the Space or Enter keys. Simply, if nosotros do care, nosotros can have advantage of the keyup event properties to notation which is which.

Buried in the various specifications about the click event (which leads us to the UI Events specification) there are certain properties assigned to the event. Some browsers have more, just I want to focus on the particular property for the moment. This holding is tied directly to the mouse input that fired the event itself. So if the mouse push button was used then the holding should return a 1 as the value. Information technology can likewise potentially written report a higher number representing multiple clicks that is frequently tied to the double-click threshold adamant by the Os of the device. As a bonus, this property reports a naught for the click event being caused by something other than the mouse input, such as the keyboard.

I'll take a moment for a shout out to Jimmy down in the comments. I originally had a different method to determining keyboard versus mouse clicking, yet it wasn't consistent beyond all browsers since Safari reported values slightly dissimilar. Jimmy suggested the detail property as it was more consistent; so I updated my examples accordingly. Cheers to Jimmy for the suggestion!

Here's our new code:

          const button = document.querySelector('#button');  push.addEventListener('click', (e) => {   button.innerText = e.particular === 0 ? 'Keyboard Click Event!' : 'Mouse Click Effect!';      window.setTimeout(() => {     push button.innerText = '"click" me';   }, 2000); });        

Dorsum to just the click issue, but this time we await for the property value to determine whether this is a keyboard or mouse "click." Although notice we no longer have a way to make up one's mind what fundamental was used on the keyboard, only that is not much of a concern in this context.

Which 1 out of many?

At present is a good time to talk nearly Pointer Events. As described by MDN:

Much of today's web content assumes the user's pointing device volition be a mouse. Still, since many devices support other types of pointing input devices, such as pen/stylus and touch surfaces, extensions to the existing pointing device event models are needed. Pointer events accost that demand.

And then now let's consider having a need for knowing what type of pointer was involved in clicking that push. Relying on merely the click issue doesn't actually provide this information. Chrome does have an interesting holding in the click event, sourceCapabilities. This property in turn has a holding named firesTouchEvents that is a boolean. This information isn't always available since Firefox and Safari do not support this notwithstanding. Yet the arrow consequence is available much everywhere, even IE11 of all browsers.

This event tin can provide interesting information about touch or pen events. Things like pressure, contact size, tilt, and more. For our example hither we're just going to focus on pointerType, which tells us the device type that caused the consequence.

Another point to make in relation to the particular property in the click event mentioned above. The pointer consequence besides has a detail property simply at this time the spec states that the value of that belongings should always be naught. Which apparently conflicts with the previous idea that a value of zero means the keyboard and a value above zero means mouse input. Since we can't rely on that belongings in the pointer result, that it makes it difficult to include both click and pointer events inside the same situation. To be fair, you probably wouldn't want to do that anyhow.

Clicking on the button will at present tell y'all the pointer that was used. The code for this is quite simple:

          const push = document.querySelector('#button');  button.addEventListener('pointerup', (e) => {   button.innerText = `Pointer Consequence: ${e.pointerType}`;      window.setTimeout(() => {     button.innerText = '"click" me';   }, 2000); });        

Really, not that much unlike than the previous examples. We heed for the pointerup event on the push button and output the event's pointerType. The difference now is there is no upshot listener for a click event. Then tabbing onto the button and using infinite or enter key does goose egg. The click event still fires, but we're non listening for it. At this point we only accept code tied to the button that just responds to the pointer event.

That plainly leaves a gap in functionality, the keyboard interactivity, so nosotros still demand to include a click outcome. Since we're already using the pointer event for the more traditional mouse click (and other pointer events) nosotros have to lock downwards the click event. We need to only allow the keyboard itself to trigger the click issue.

The code for this is like to the "Which Is Which" example upward above. The divergence being we apply pointerup instead of mouseup:

          const push = document.querySelector('#push button');  office reset () {   window.setTimeout(() => {     push button.innerText = '"click" me';   }, 2000); }  button.addEventListener('pointerup', (eastward) => {   button.innerText = `Pointer Outcome: ${e.pointerType}`;   reset(); });  button.addEventListener('click', (east) => {   if (eastward.detail === 0) {     push.innerText = 'Keyboard  ||Click Event!';     reset();   } });        

Here nosotros're using the detail belongings again to decide if the click was acquired by the keyboard. This style a mouse click would exist handled by the arrow outcome. If one wanted to know if the key used was space or enter, so the keyup instance higher up could be used. Fifty-fifty and then, the keyup event could be used instead of the click event depending on how you wanted to approach it.

Anoher accept to decide which 1 out of many

In the ever-present need to refactor for cleaner code, we can try a different way to code this.

Yep, works the same equally before. Now the lawmaking is:

          const button = certificate.querySelector('#push');  function btn_handler (eastward) {   if (eastward.blazon === 'click' && e.particular > 0) {     return false;   } else if (e.pointerType) {     button.innerText = `Pointer Result: ${e.pointerType}`;   } else if (e.detail === 0) {     push button.innerText = 'Keyboard Click Issue!';   } else {     push button.innerText = 'Something clicked this?';   }      window.setTimeout(() => {     push.innerText = '"click" me';   }, 2000); }  button.addEventListener('pointerup', btn_handler); push.addEventListener('click', btn_handler);        

Another scaled downwards version to consider: this time we've reduced our code downwards to a single handler method that both pointerup and click events call. First nosotros detect if the mouse "click" caused the issue because the particular property has a value higher than zero; if information technology does, we wish to ignore information technology in favor of the pointer event.

Then the method checks for the arrow event, and upon finding that, information technology reports which pointer blazon occurred. Otherwise, the method checks for keyboard interactions, if item equals zero, and reports accordingly. If neither of those are the culprit, it just reports that something acquired this code to run.

And so here we have a decent number of examples on how to handle push button interactions while reporting the source of those interactions. Yet, this is simply i of the handful of form elements that we are and so accustomed to using in projects. How does similar code work with other elements?

Checking checkboxes

Indeed, similar code does work very much the same mode with checkboxes.

At that place are a few more nuances, as you lot might expect by now. The normal usage of <input blazon="checkbox"> is a related label element that is tied to the input via the for attribute. One major feature of this combination is that clicking on the label element will check the related checkbox.

Now, if we were to attach event listeners for the click issue on both elements, nosotros get back what should be obvious results, even if they are a fleck foreign. For example, we get one click outcome fired when clicking the checkbox. If we click the label, we get 2 click events fired instead. If nosotros were to panel.log the target of those events, we'll see on the double issue that one is for the label (which makes sense every bit we clicked it), but there's a second result from the checkbox. Even though I know these should exist the expected results, it is a bit strange because we're expecting results from user interactions. Yet the results include interactions acquired past the browser.

And so, the next step is to look at what happens if we were to mind for pointerup, only like some of the previous examples, in the same scenarios. In that case, nosotros don't get two events when clicking on the label element. This besides makes sense as nosotros're no longer listening for the click event that is existence fired from the checkbox when the characterization is clicked.

There's still another scenario to consider. Retrieve that we have the option to put the checkbox within the characterization element, which is mutual with custom-built checkboxes for styling purposes.

          <label for="newsletter">   <input blazon="checkbox" />   Subscribe to my newsletter </label>        

In this case, we really only need to put an upshot listener on the label and non the checkbox itself. This reduces the number of upshot listeners involved, and yet nosotros get the aforementioned results. Clicks events are fired as a unmarried effect for clicking on the label and two events if you click on the checkbox. The pointerup events do the aforementioned as before as well, single events if clicking on either chemical element.

These are all things to consider when trying to mimic the behavior of the previous examples with the button chemical element. Thankfully, there's not too much to information technology. Here's an example of seeing what type of interaction was done with a checkbox form element:

This case includes both types of checkbox scenarios mentioned to a higher place; the top line is a checkbox/label combination with the for attribute, and the bottom one is a checkbox inside the label. Clicking either one will output a bulletin below them stating which type of interaction happened. So click on one with a mouse or utilize the keyboard to navigate to them and so interact with Space; only like the button examples, it should tell you lot which interaction type causes it.

To brand things easier in terms of how many upshot listeners I needed, I wrapped the checkboxes with a container div that actually responds to the checkbox interactions. You wouldn't necessarily have to do information technology this way, simply it was a convenient mode to do this for my needs.

          const checkbox_container = document.querySelector('#checkbox_container'); const checkbox_msg = document.querySelector('#checkbox_msg');  function chk_handler (e) {   if (due east.target.tagName === 'Characterization' || e.target.tagName === 'INPUT') {     if (e.pointerType) {       checkbox_msg.innerText = `Arrow Event: ${due east.pointerType}`;     } else if (east.code === 'Space') {       checkbox_msg.innerText = `Keyboard Outcome: ${e.lawmaking}`;     }          window.setTimeout(() => {       checkbox_msg.innerText = 'waiting...';     }, 2000);   } }  checkbox_container.addEventListener('pointerup', chk_handler); checkbox_container.addEventListener('keyup', chk_handler);        

So, since we're listening for these events on a container div I wanted to lock down the targets to simply the characterization and the input. Technically information technology would exist possible in some cases to "click" on the container div itself; which nosotros wouldn't desire to happen. So nosotros bank check for a arrow event and update the message. Afterwards that we endeavour to identify the Space key lawmaking that would have come from the keyup issue. You may retrieve that the button examples above used both the Enter and Space keys. It turns out that checkboxes often don't react to the Enter key in browsers. Another fun nuance to keep in listen.

Radioing your radio buttons

Thankfully, for radio button inputs, we can nevertheless employ the aforementioned code with similar HTML structures. This mostly works the aforementioned considering checkboxes and radio buttons are substantially created the same way—it's just that radio buttons tend to come in groups tied together while checkboxes are individuals even in a group. As you'll come across in the following example, it works the same:

Again, aforementioned code attached to a similar container div to prevent having to do a number of event listeners for every related chemical element.

When a nuance can exist an opportunity

I felt that "dash" was a expert word choice because the things we covered here are not really "problems" with the typical negative connotation that word tends to have in programming circles. I always try to run across such things as learning experiences or opportunities. How can I leverage things I know today to push a little further ahead, or perchance it'due south time to explore outward into new things to solve issues I face. Hopefully, the examples above provide a somewhat different style to look at things depending on the needs of the project at hand.

Despite this commodity focusing more on class elements because of the click dash they tend to have with keyboard interactions, some or all of this can exist expanded into other elements. It all depends on the context of the situation. For example, I recall having to do multiple events on the same elements depending on the context many times; often for accessibility and keyboard navigation reasons. Have y'all built a custom <select> chemical element to have a nicer blueprint than the standard one, that also responds to keyboard navigation? You'll see what I mean when you get at that place.

But remember: a "click" today doesn't always have to be what we think a click has always been.

alibuithe.blogspot.com

Source: https://css-tricks.com/when-a-click-is-not-just-a-click/

Mag-post ng isang Komento for "Javascript Function on Click and Click Again"