Capture delete key if not focused in a form - javascript

I have a web app which plots points with SVG, I want to add the ability to delete a selected point by pressing the delete key. I can capture delete keydown (or up) for the entire document and prevent the default event (Chrome's default behavior is to go back a page), however this obviously blocks all delete events so the delete button no longer works in forms.
Is there a way to set it up so that the delete key works as intended in forms/inputs but when anywhere else in the app it can be used as a custom delete function?

The first thing that came into my mind, is to stopPropagation on the input and textarea fields, then the preventDefault should not be triggered on the document.
JQuery pseudo code:
$('input, textarea').keypress(e, function(e){e.stopPropagation();});
$(document).keypress(e, function(e){if(delete) e.preventDefault();});
Another possiblity is the check the orignal target on the key event of the document.
Event callback:
var originalElement = e.srcElement || e.originalTarget;
if(orignalElement.tagName === 'INPUT' or orignalElement.tagName === 'TEXTAREA'){ return; }
// else do your delete key stuff
The first line should be obsolete, if you are using jQuery, because it normalized the event for you, and you can use e.target to get the originalTarget

My prefered approach would be something like this:
$(window).keyup(function(e) {
if(e.keyCode == 46 && $("input:focus, textarea:focus").length == 0) {
e.preventDefault();
alert("delete key pressed!");
}
});
However, I'm not sure if you'll be able to override the back button behaviour - it seems unlikely that Chrome would allow it, given the potential for abuse.

Related

JavaScript - JQuery - focus() method - infinite loop

I'm trying to build a functionality that allows keyboard tabbing between two buttons (CodePen below). More specifically I would like the user to be able to tab onto "button1" and on tab, jump to "button2" and then on tab jump back to button 1.
My solution is to put an event listener on "button1" and listen for a tab keyboard event. When that is triggered, use JQuery's focus() method to shift focus to "button2". On "button2" there is an identical listener that listens for tab event and shift focus back to "button1".
The problem is that when I tab onto "button1", the listener records focus and tab event and shift focus onto "button2" which in turn records focus and tab event and shift it back to "button1" again, creating an infinite loop.
Could I please get suggestions in how to solve this problem?
The real world application of this would be to restrict tabbing within a specific module or section of a page.
Thanks!
Steve
https://codepen.io/steveliu7/pen/WOoMJY
var $button1 = $('.b1');
var $button2 = $('.b2');
var checkButton = function(event) {
if ($button1.is(':focus') && event.which === 9){
console.log($(this))
$('.b2').focus();
return;
};
if ($button2.is(':focus') && event.which === 9){
console.log($(this))
$('.b1').focus();
return;
};
}
$('button').on('keydown', checkButton);
You want to restrict tab navigation between two buttons.
Note that it won't restrict screenreaders navigation to those two buttons.
You have to consider TAB navigation but also SHIFT+TAB navigation
On a purely technical point of view event.preventDefault() is what your are searching for:
var checkButton = function(event) {
if (event.which === 9) {
if ($button1.is(':focus')) {
$button2.focus();
event.preventDefault();
} else if ($button2.is(':focus')){
$button1.focus();
event.preventDefault();
}
}
}
I think what you are trying to do can be achieved much easier with the tabindex property in HTML. If you want to restrict tabbing to certain elements only, you can set tabindex="-1" for those elements that you do not want focused.
Source: https://www.w3schools.com/tags/att_global_tabindex.asp

Global on enter function for all elements

i have written a code :
$('*').on('keyup',function(e){
if(e.keyCode == 13){
$(this).trigger('click');
}
});
the above code works fine until jquery dialog. Apparently whenever i hit an enter key in the dialog. it sort of like bubbles up the event.
i have 2 dialogs. 1st is the confirm dialog and 2nd is the message dialog. when i hit yes it will pop up the message dialog and when i hit ok on the message dialog the confirm dialog will open again.
i tried like this :
$('*').not('.ui-button').on('keyup',function(e){
if(e.keyCode == 13){
$(this).trigger('click');
}
});
this is for the exclusion of the ui-buttons for the enter events. it did not work. Any help would be appreciated. thanks
EDIT :
note that i call the dialogs to open using a link. i wonder if that link is focused when i hit enter so it calls the dialog again when i hit enter on the message dialog.
Why not cancel its event by using off?
$('*').on('keyup',function(e){
if(e.keyCode == 13){
$(this).trigger('click');
}
}).find(".ui-buttons").off('keyup'); // this unbinds the event so it won't trigger
It might be that the ui buttons are not created when the handlers are registered.
One approach you can do is to register a single handler to the document object, then see whether the actual target is a ui-button like
$(document).on('keyup', function (e) {
var $target = $(e.target);
if ($target.closest('.ui-button').length) {
return;
}
if (e.keyCode == 13) {
$target.trigger('click');
}
});
use this code, this code exclude .ui-button element and inner elements of .ui-button class
$('body').on('keyup',function(e){
if(!$(e.target).closest('.ui-button').length && e.keyCode == 13){
$(e.target).trigger('click');
}
});
I admit I'm not a big fan of global bindings, especially because of these problems. I find it better to specify the types and/or location of the elements I want to bind the event to.
One of the reasons is this event bubbling that sadly does not behave the same way in all browsers.
My suggestion is to bind the event only to the desired elements and add e.stopPropagation() to the called function(s).
I know this is not the answer you were looking for but I believe you should consider this method for being more specific (and more reliable).
I fixed the problem by blurring the link that i clicked to open the dialog.
something like :
$('.links').find('a').on('click',function(){
$(this).blur();
});

How to bind multiple actions to a keyboard event [duplicate]

This question already has an answer here:
override existing onkeydown function
(1 answer)
Closed 7 years ago.
I am trying to make a chrome extension that modifies the text in an active text area of a Facebook chat window. But I want the change to take place only when the user presses the enter key so that the text doesn't change while it is still in the textarea. I want it to happen using javascript and make it feel like it's happening in the background although I want it to get triggered on the keydown event of the enter key.
Now the relevant JavaScript for the chat window's textarea in Facebook is:
<textarea class="blah"
onkeydown="window.Bootloader && Bootloader.loadComponents(["control-textarea"],
function() { TextAreaControl.getInstance(this) }.bind(this)); ">
</textarea>
And in my extension's JavaScript file. I bind the keydown event using something like this:
//elem is bound to the focussed textarea object
elem.onkeydown = function(evt) {
if(evt.keyCode == 13){
//Some javascript code I want to execute here...
}
};
I think as soon as the user presses the enter key, the textarea is cleared and some sort of a post request is made. So I lose the scope of the text I wanted to modify using JavaScript. I checked that the enter key binding is working for my extension by pressing shift + enter, and it modified the text without a problem. So my script is working fine.
However I want my script to be executed before the textarea is cleared and the post request is made. I just don't want the user to see the text getting modified.
Can I add/modify the keybinding of the textarea used by Facebook as shown above in my script for the google chrome extension? Any help is deeply appreciated.
There are a million duplicates of this question on here, but here goes again anyway:
You can use target.addEventListener(type, listener[, useCapture]); In your case, it would be
document.addEventListner(keypress, function(event) { //You can use keydown too
if (event.which === 13) { // Value for Enter key if keydown or keyup used, use event.keyCode
//some code that you want to add
}
}
If you are using jQuery, you can use
$(document).keypress(function(event){
if (event.which === 13) {
// Your code here
}
});
P.S. - In case of adding crossbrowser support, you should use something like this:-
if (target.addEventListener) {
target.addEventListener('keypress',myFunction,false);
}
else if(target.attachEvent) {
target.attachEvent('onkeypress', myFunction, false);
} else {
target.onkeypress = myFunction;
}
// Here myFunction is the callback where you would check for the character code and your custom code

Jump to next input field with arrow keys using jQuery in form

I want to use the arrow keys to navigate between the input text fields in my form (next, previous). I found this simple method to implement it: link to it but for me it doesn't work... I tried it in the HEAD and in the BODY after the FORM as well, but no luck...
I think the problem could be, that my form is send back to the page via AJAX...
I'm not that familiar with jQuery, can someone please help me out here?
This is the jQuery code:
<script>
$(document).ready(function(){
$('input').keyup(function(e){
if(e.which==39)
$(this).closest('td').next().find('input').focus();
else if(e.which==37)
$(this).closest('td').prev().find('input').focus();
else if(e.which==40)
$(this).closest('tr').next().find('td:eq('+$(this).closest('td').index()+')').find('input').focus();
else if(e.which==38)
$(this).closest('tr').prev().find('td:eq('+$(this).closest('td').index()+')').find('input').focus();
});
});
</script>
if your inputs are dynamically created after domready event you should change
$('input').keyup(function(e){
...
into
$('body').on('keyup', 'input', function(e) {
...
doing so the keyup event will be captured on body element using event delegation
For further info see the documentation here: http://api.jquery.com/on/
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on(). To ensure the elements are present and can be selected, perform event binding inside a document ready handler for elements that are in the HTML markup on the page. If new HTML is being injected into the page, select the elements and attach event handlers after the new HTML is placed into the page. Or, use delegated events to attach an event handler...
If your script is loaded before the form is on the page then the keyup binding would not be able to bind on load. Try using:
$('input').live('keyup', function(e) { code here });
Just in case you want to bind more than one event, this is how you do it:
$('body').on({
'keyup' : function(e) {
...
},
'keydown' : function(e) {
...
}
}, 'input');
Also 'body' can be swapped with any parent element of 'input' that will not be dynamically added to the page (i.e. it exists on page load). So if you have some div containing each input, you might want to bind that instead.
I've got a slight improvement to the code above. The problem with the code is that you cannot navigate inside an input field. E.g. you have a value of '100.00|' with the cursor currently at the end (indicated with |). If you press the left key it will jump to the prev input field instead of moving the caret by one position to '100.0|0'.
In order to do that you need to check the current caret position with e.target.selectionStart. But you also need the prev caret position as otherwise you can't identify whether the caret went from 1 to 0 (no jump) or the caret was already on 0 and the user pressed left again (jump).
Another change I've added is that only input fields with the class tableInput are considered. In case you want to exclude some fields.
function(e){
var charPos = e.target.selectionStart;
var strLength = e.target.value.length;
var prevPos = $(this).data('prevPos');
if(e.which==39){
//only go right if we really reached the end, that means the prev pos is the same then the current pos
if(charPos==strLength && (prevPos ==null || prevPos == charPos)){
$(this).closest('td').next().find('input.tableInput').focus();
$(this).data('prevPos',null);
}else{
$(this).data('prevPos',charPos);
}
}else if(e.which==37){
//only go left if we really reached the beginning, that means the prev pos is the same then the current pos
if(charPos == 0 && (prevPos ==null || prevPos == charPos)){
$(this).closest('td').prev().find('input.tableInput').focus();
$(this).data('prevPos',null);
}else{
$(this).data('prevPos',charPos);
}
}else if(e.which==40){
$(this).closest('tr').next().find('td:eq('+$(this).closest('td').index()+')').find('input.tableInput').focus();
$(this).data('prevPos',null);
}else if(e.which==38){
$(this).closest('tr').prev().find('td:eq('+$(this).closest('td').index()+')').find('input.tableInput').focus();
$(this).data('prevPos',null);
}
});

how to remove the default focus on submit button in HTML form?

I have a HTML form on my page. When i am putting some value in one of the text fields in form and press 'Enter key' the form gets submitted instantly. I think this is happening due to default focus is on submit button. But i try to remove that focus using blur() function, it is not working. I am using Chrome.
Is there any way to avoid this scenario?
All suggestions are welcome. thanks in advance.
The Submit button is not actually focused; Enter in a text field is supposed to submit the form.
You could register a handler for the submit event, and then only allow it if the Submit button was actually focused at the time submit was requested.
However, you'll be deliberately breaking the way that HTML forms work. Not everyone wants to submit the form using the One True Way of actually clicking the Submit button (also, you'll be breaking accessibility and may introduce browser-specific bugs).
No. The focus is still on the text field. Pressing enter there is supposed to submit the form (and bypasses the submit button entirely).
You can suppress the behavior using JavaScript, but since it is normal behavior for the browser, I wouldn't recommend doing so.
try this solution: replace the 'input' with 'button' and add attribute
type equals 'button' and handle the onclick event with submit javascript function
<form name='testForm'>
<input type='text' value="myName" />
<button type='button' onclick='testForm.submit()'/>
</form>
i think it works also with tag input adding the same attribute
Enjoy
Mirco
blur() is the way to go. It works like this:
<button onclick="this.blur();">some button</button>
Note that you should not use JavaScript and DOM-events using Attributes. This is just for demonstration purposes. Try to be unobstrusive.
Maybe it will help you out, the form is "supposed" to be sent with enter in the text box (HTML by design), it is no a matter of focus.
If you want to avoid it, check this out.
This is the proposed script:
function disableEnterKey(e)
{
var key;
if(window.event)
key = window.event.keyCode; //IE
else
key = e.which; //firefox
return (key != 13);
}
Good luck, tell me if you need any clarification!
EDIT: I do agree with Piskvor answer, it may bring some bugs
this has nothing to do with the focus, its just the default behavior of you browser. to avoid this, you could try to cath the enter-keypress like this (Source - but there are a lot of other solutions (most working the same way, just using other events like the firms onsubmit instead of the documents onkeypress)):
function catchEnter(e){
// Catch IE’s window.event if the
// ‘e’ variable is null.
// FireFox and others populate the
// e variable automagically.
if (!e) e = window.event;
// Catch the keyCode into a variable.
// IE = keyCode, DOM = which.
var code = (e.keyCode) ? e.keyCode : e.which;
// If code = 13 (enter) or 3 (return),
// cancel it out; else keep going and
// process the key.
if (code == 13 || code == 3)
return false;
else
return true;
}
// Anonymous method to push the onkeypress
// onto the document.
// You could finegrain this by
// document.formName.onkeypress or even on a control.
window.onload = function() { document.onkeypress = catchEnter; };
Change:
<input type="text" ... >
To:
<textarea ... ></textarea>
You may need to mess around with the attributes a bit, I've left them signified as ....
try to add on the keypress event of your button this javascript function :
function ButtonKeyPress()
{
var code = (window.event.which) ? window.event.which : window.event.keyCode;
if ( code == 13 )
{
event.returnValue = false;
return false;
}
return true;
}
So, you have a form. In this form, you have a text input, and a submit button.
You get in the text input, you type some text, than you press "Enter". This submits the form.
You would like to break this normal behavior.
I think this is not a good idea : The convention says that when your in a text input and press "Enter", it submits the form. If you change this behavior, users could be (I don't find the right word, let's say ~) surprised.
Anyway, if you still want to do this, you should listen for the keypress event on the text input, and than prevent default behaviour shoud do the work.
let's say you use jQuery :
$(input[type=text]).bind('keypress', function(evt) {
if(evt.keyCode == 13) {
evt.preventDefault();
}
});
This should do it. I didn't test it, maybe I made mistakes, but you got the idea, no ?
And maybe keyup is better than keypress... I don't know very well this, not enough practice on key bindings
The easiest way is to set css style like this:
&:focus {
outline: 0 none;
}

Categories

Resources