Trigger click event on keypress for any focused element - javascript

Is there a default way to trigger a click event anytime enter is pressed on a focused element?
What I am referencing is the differences from pressing enter while focused on a <button> vs. pressing enter while focused on a <div> <li> <span>, etc. The <button> keypress enter triggers as expected. However, <div> keypress enter does nothing. I believe you have to specifically write the event in for that keypress.
$('li').click(function() {
//toggles something
});
$("li").keydown(function(e){
if(e.which === 13){
$(this).click();
}
});

Is there a default way to trigger a click event anytime enter is pressed on a focused element?
There's no solution without javascript.
Although the onclick has a special behavior as the W3C mentions
While "onclick" sounds like it is tied to the mouse, the onclick event is actually mapped to the default action of a link or button.
this does not work with other elements than links and buttons.
You could be tempted to add role="button" to a div with a tabindex="0". This does not work.
The Mozilla documentation explicitely says that you have to define handler, even with the button role.
This is easily understandable as this is a browser feature. When you define role=link on an element, you can't right click on it, hoping that it will open your browser context menu. For the same reason, defining the role=button attribute won't affect the default behavior. From this discussion:
ARIA simply conveys the accessibility semantics
intended by the author that are conveyed to an assistive technology.
Also do not forget to handle the space key. Read Karl Groves article and example about the subject.

If the elements on your page already have click events, and are in the tab order, and you just want to make the enter key trigger a click on whichever element has focus for accessibility, try the following:
<head>
<script>​
function handleEnter(e){​
var keycode = (e.keyCode ? e.keyCode : e.which);​
if (keycode == '13') {​
document.activeElement.click();​
}​
}​
</script>​
</head>​
​
<body onkeypress="handleEnter(event)">
This is especially useful for adding play/pause and making other image based controls accessible in banner ads made with Google Web Designer.

Certain HTML Elements such as span, li, div doesn't not have really have a focused state hence the focus won't trigger. What can be done in order to give the element a possible focus state is to add a tabindex and it will work, e.g:
<div tabindex="0"></div>

When I listen for keyboard events on a list, I put the handler on the <ul> instead of the <li> and it works great. It might work on the <li> as well but your example above sounds like it doesn't.

Related

Why doesn't simulating a tab keypress move focus to the next input field?

Note this question. I see that there are other approaches besides just triggering the tab keypress event, but I'd still like to know why triggering the tab key press event doesn't move focus to the next input field.
Code Pen
HTML
<textarea></textarea>
<textarea></textarea>
<textarea></textarea>
JS
$('textarea').on('keydown', function(e) {
if (e.metaKey && e.which === 40) {
console.log('test');
$(this).trigger({
type: 'keypress',
which: 9
});
}
});
Because the tab event is a native browser event/action for changing focus. The .trigger() function only triggers the event handlers that are assigned to it. Note there is more information given from jQuery's site:
The .trigger() function cannot be used to mimic native browser events, such as clicking on a file input box or an anchor tag. This is because, there is no event handler attached using jQuery's event system that corresponds to these events.
There is a plug-in for this though called jquery-simulate to handle this. That being said the tab key changing focus is actually a default action in the web browser. Firing a browsers native event does not mean it will do it's default action, as the documentation for KeyboardEvents mentions:
Note that manually firing an event does not generate the default action associated with that event. For example, manually firing a key event does not cause that letter to appear in a focused text input. In the case of UI events, this is important for security reasons, as it prevents scripts from simulating user actions that interact with the browser itself.

Checking how an element gained focus

Context
I have a backbone app with an event listener for focus events on a textarea. Backbone uses jQuery events, so core of my question centers around jQuery focus events.
Question
Is there a way to tell how an element came into focus, be it by click or tab?
The behavior of how the cursor gets positioned needs to be handled differently between these two cases, however there doesn't seem to be a way to distinguish between the two offhand.
I could listen to click events, however will still need to listen to focus to capture tabbing - this will overlap with click event as it will also focus the textarea resulting in double events.
I may to rethink this entirely.
JSBin Example
$('textarea')
.focus(function(event){
console.log('You focused me by' + event.type);
// Here I wish I know if the focus came from a 'click' or 'tab' events
});
<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
<form>
<input placeholder="focus me, then tab" type="text"><br>
<textarea>Focus me via click. Now try via tabbing.</textarea>
</form>
</body>
</html>
.onfocus() listener can get called in a number of ways which makes it a tricky even to bind to.
Click on element
Tab or Shift-Tab to element
jQuery programatic focus $( "#target" ).focus();
Switching between programs, and refocusing the internet browser
There is no unique identifier in the onfocus event to determine how it came into focus.
From what I found it is best to be more explicit and listen to click() and onkeyup() events to handle unique behaviors between them and avoid unexpected function calls (like the browser is refocused).
onkeyup() is great for capturing tab events as the tab key will be released 'up' when tabbing in, but not when tabbing out.
JSBin
$('textarea')
.click(focusedBy)
.keyup(checkTab);
function checkTab(event){
if (event.keyCode === 9) {
focusedBy(event);
}
}
function focusedBy (event){
console.log('You focused me by ' + event.type);
}
you will need a combo of focus, click and blur events to determine the origin of "getting focus". click->set value, focus -> check if that clickvalue was set -> do what you must -> reset on blur. you might also want to be looking out for ontouchdown
You could set a clicked variable on mousedown.
You'll need to blur the textarea on mousedown so that focus will will be triggered on mouseup:
var clicked= false;
$('textarea')
.focus(function(event) {
if(clicked) {
$('#status').html('clicked');
clicked= false;
}
else {
$('#status').html('tabbed');
}
})
.mousedown(function(event) {
clicked= true;
$(this).blur();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<input placeholder="focus me, then tab" type="text"><br>
<textarea>Focus me via click. Now try via tabbing.</textarea>
</form>
<div id="status"></div>
here's a scaling way to do it without rerouting events or simulating extra actions:
var targ=$('textarea');
targ.focus(function(event){
console.log('You focused me by ' + targ.eventType);
// Here I wish I know if the focus came from a 'click' or 'tab' events
});
$("body").mousedown(function(e){
targ.eventType="mouse";
}).keydown(function(e){
targ.eventType="keyboard";
});
this uses the jQuery collection to store the last event type, which is set by document-wide handlers.
if you need to re-use this functionality on other input types, just add more selectors to targ and differentiate in the handler using event.target.
http://jsbin.com/ruqekequva/2/edit

Space and enter "click" on the input that's focused. How do I disable this behavior?

In chrome and firefox (and maybe others), if you've got an input focused, pressing "space" and "enter" clicks them for you. I'm making an HTML 5 game and I want to rewrite how space and enter reacts on focus and the default behavior is getting in my way. Is there a way to turn this default behavior off in most browsers?
Here's a jsfiddle demonstrating the problem.
<button>Button<button>
$("button").on("click", function(event) { alert("Clicked"); });
If you click on the button, it displays the alert which is good. But if you press "space" or "enter" after you click it, it also alerts. I want to prevent this behavior so that I can write my own without them interfering.
You can fix this by using event.detail. That will return the amount of times the button has been clicked. If you press enter, this returns 0, since you clicked it 0 times, and if you click it via your mouse, it returns the amount of times you clicked the button.
To access event.detail, you need to access the original event object. This can be done via event.originalEvent in the jQuery event object. So, if you just put an if statement in your script:
if (event.originalEvent.detail != 0) {
//your click event code
}
then it'll only run if you actually click the button via your mouse.
This will be much more accurate than checking if the button has :focus, since the button automatically gets focused when you click it, so doing that would disable the button after a single click.
Check if a button is active:
$("button").on("click", function(event) { alert("Clicked"); });
$(document).on('keydown', function(e){
if($(document.activeElement).is('button') &&
(e.keyCode === 13 || e.keyCode === 32))
e.preventDefault();
});
You could also use jQuery's :focus selector, which should return the same element, $(':focus').is('button').
http://jsfiddle.net/zmH5V/4/
other option, is to blur the object right after clicking it:
<button id="mybutton" onclick="myFunction();this.blur();">button</button>
I find that solution easier to use, because it requires less code-lines, and gets the same results:
while the button is blured, it has no contact with the keyboards events, and that solves the problem.

How to prevent HREF (which calls JS function) from being triggered when "Enter" key is pressed?

I am facing a problem.
I have a href which calls a javascript function "delete_element_on_page" when i click on it.
So when i click the HREF with my mouse, everything is fine and the function gets called.
However, because the HREF has focus, if keep hitting my enter key, the function gets called again and again and again leading to undesired outcomes.
How can i prevent this from happening?
I was thinking of
1. Blurring the focus on the href when my function is called
--> I could do this, but this will mean I have to manually do this for every single HREF because jquery.blur can only be triggered at an individual element level.
--> Alternatively, is there a javascript equivalent of where I can do a universal Blurring, regardless of which element is in focus?
OR
Deactivate enter key from triggering clicking of a HREF
--> Is this even possible? And if so, worth my while in terms of code complexity / compatibility etc..
Thanks so much :)
You can bind your event and avoid placing the javascript trigger inside the html tag.
With jQuery (the easy and more reliable way) you do that like this:
<script src="http://code.jquery.com/jquery.min.js"></script>
<script>
$("#myelementid").bind("click",function(e){
e.preventDefault(); // important, to prevent trigering the default a href
// your code goes here
$(this).blur();
});
</script>
The above answers will block both keyboard click and mouse click this will block the enter key from doing anything on that link. So it corresponds to #2
<a id="fail" href="http://jquery.com">default click action is prevented</a>
<script>
$("#fail").keydown(function(event) {
event.preventDefault();
});
</script>
you can bind click event handle it by jquery, using href for calling js functions is not recommended:
$("a#id").click(function(){
// the code goes here;
})

Blur event stops click event from working?

It appears that the Blur event stops the click event handler from working? I have a combo box where the options only appear when the text field has focus. Choosing an option link should cause an event to occur.
I have a fiddle example here: http://jsfiddle.net/uXq5p/6/
To reproduce:
Select the text box
Links appear
Click a link
The blur even occurs and the links disappear
Nothing else happens.
Expected behavior:
On step 5, after blur occurs, the click even should also then fire. How do I make that happen?
UPDATE:
After playing with this for a while, it seems that someone has gone to great lengths to prevent an already-occurred click event from being handled if a blur event makes the clicked element Un-clickable.
For example:
$('#ShippingGroupListWrapper').css('left','-20px');
works just fine, but
$('#ShippingGroupListWrapper').css('left','-2000px');
prevents the click event.
This appears to be a bug in Firefox, since making an element un-clickable should prevent future clicks, but not cancel ones that have already occurred when it could be clicked.
Other things that prevent the click event from processing:
$('#ShippingGroupListWrapper').css('z-index','-20');
$('#ShippingGroupListWrapper').css('display','none');
$('#ShippingGroupListWrapper').css('visibility','hidden');
$('#ShippingGroupListWrapper').css('opacity','.5');
I've found a few other questions on this site that are having similar problems. There seem to be two solutions floating around:
Use a delay. This is bad because it creates a race condition between the hiding and the click event handler. Its also sloppy.
Use the mousedown event. But this isn't a great solution either since click is the correct event for a link. The behavior of mousedown is counter-intuitive from a UX perspective, particularly since you can't cancel the click by moving the mouse off the element before releasing the button.
I can think of a few more.
3.Use mouseover and mouseout on the link to enable/disable the blur event for the field. This doesn't work with keyboard tabing since the mouse is not involved.
4.The best solution would be something like:
$('#ShippingGroup').blur(function()
{
if($(document.activeElement) == $('.ShippingGroupLinkList'))
return; // The element that now has focus is a link, do nothing
$('#ShippingGroupListWrapper').css('display','none'); // hide it.
}
Unfortunately, $(document.activeElement) seems to always return the body element, not the one that was clicked. But maybe if there was a reliable way to know either 1. which element now has focus or two, which element caused the blur (not which element is blurring) from within the blur handler. Also, is there any other event (besides mousedown) that fires before blur?
click event triggers after the blur so the link gets hidden. Instead of click use mousedown it will work.
$('.ShippingGroupLinkList').live("mousedown", function(e) {
alert('You wont see me if your cursor was in the text box');
});
Other alternative is to have some delay before you hide the links on blur event. Its upto you which approach to go for.
Demo
You could try the mousedown event instead of click.
$('.ShippingGroupLinkList').live("mousedown", function(e) {
alert('You wont see me if your cursor was in the text box');
});
This is clearly not the best solution as a mousedown event is not achieved the same way for the user than a click event. Unfortunately, the blur event will cancel out mouseup events as well.
Performing an action that should happen on a click on a mousedown is bad UX. Instead, what's a click effectively made up of? A mousedown and a mouseup.
Therefore, stop the propagation of the mousedown event in the mousedown handler, and perform the action in the mouseup handler.
An example in ReactJS:
<a onMouseDown={e => e.preventDefault()}
onMouseUp={() => alert("CLICK")}>
Click me!
</a>
4.The best solution would be something like:
$('#ShippingGroup').blur(function()
{
if($(document.activeElement) == $('.ShippingGroupLinkList'))
return; // The element that now has focus is a link, do nothing
$('#ShippingGroupListWrapper').css('display','none'); // hide it.
}
Unfortunately, $(document.activeElement) seems to always return the
body element, not the one that was clicked. But maybe if there was a
reliable way to know either 1. which element now has focus or two,
which element caused the blur (not which element is blurring) from
within the blur handler.
What you may be looking for is e.relatedTarget. So when clicking the link, e.relatedTarget should get populated with the link element, so in your blur handler, you can choose not to hide the container if the element clicked is within the container (or compare it directly with the link):
$('#ShippingGroup').blur(function(e)
{
if(!e.relatedTarget || !e.currentTarget.contains(e.relatedTarget)) {
// Alt: (!e.relatedTarget || $(e.relatedTarget) == $('.ShippingGroupLinkList'))
$('#ShippingGroupListWrapper').css('display','none'); // hide it.
}
}
(relatedTarget may not be supported in older browsers for blur events, but it appears to work in latest Chrome, Firefox, and Safari)
If this.menuTarget.classList.add("hidden") is the blur behavior that hides the clickable menu, then I succeeded by waiting 100ms before invoking it.
setTimeout(() => {
this.menuTarget.classList.add()
}, 100)
This allowed the click event to be processed upon the menuTarget DOM before it was hidden.
I know this is a later reply, but I had this same issue, and a lot of these solutions didn't really work in my scenario. mousedown is not functional with forms, it can cause the enter key functionality to change on the submit button. Instead, you can set a variable _mouseclick true in the mousedown, check it in the blur, and preventDefault() if it's true. Then, in the mouseup set the variable false. I did not see issues with this, unless someone can think of any.
I have faced a similar issue while using jQuery blur, click handlers where I had an input name field and a Save button. Used blur event to populate name into a title placeholder. But when we click save immediately after typing the name, only the blur event gets fired and the save btn click event is disregarded.
The hack I used was to tap into the event object we get from blur event and check for event.relatedTarget.
PFB the code that worked for me:
$("#inputName").blur(function (event) {
title = event.target.value;
//since blur stops an immediate click event from firing - Firing click event here
if (event.relatedTarget ? event.relatedTarget.id == "btnSave" : false) {
saveBtn();
}
});
$("#btnSave").click(SaveBtn)
As already discussed in this thread - this is due to blur event blocking click event when fired simultaneously. So I have a click event registered for Save Btn calling a function which is also called when blur event's related Target is the Save button to compensate for the click event not firing.
Note: Didnt notice this issue while using native onclick and onblur handlers - tested in html.

Categories