Change accesskey modifier keys in Firefox - javascript

I'm working on a website where each page has buttons, like "submit" and "cancel". Each of these buttons has an accesskey attribute. The submit button's accesskey attribute is set to S, and the cancel button's accesskey attribute is set to C.
Access keys are activated using different modifiers in different browsers. Internet Explorer, Safari, and Google Chrome use just the alt, while Firefox uses both the alt and the shift keys. As well, Firefox uses alt + s to open the history menu.
Answers to this question should not suggest changing settings in the browser's configuration as that would not be feasible on a production site.
How I change the modifier keys that Firefox uses for accesskey's to just alt, and prevent the history menu from opening?
I am working in Ubuntu 16.04.

You cannot—as far as I can tell—change the key combination required to activate an accesskey, but what you're trying to achieve does not require use of the accesskey attribute. You can listen for the keydown event directly.
Add a keydown event listener to the document. In the handler function check to see if the alt and s keys are pressed. If they are—and no other modifier keys are pressed—prevent the default action of the event, then trigger a click event on the submit button.Triggering the click event on the submit button will in turn trigger the submit event listener, whereas triggering the submit event on the form directly may not.
const submit = document.querySelector('#submit')
document.addEventListener('keydown', e => {
// If the only modifier key is the alt key, and the s key is pressed
if(!e.metaKey && !e.ctrlKey && !e.shiftKey && e.altKey && e.key === 's') {
e.preventDefault() // Prevent the mozilla history menu from opening
submit.click() // Trigger the form submission
}
})
<form action=""><button type="submit" id="submit"><u>S</u>ubmit</button></form>
Notes:
1. Though this works in the current stable version of Firefox, I have not tested other versions
2. This example uses language features introduced in the 2015 version of The ECMAScript Language Specification. These features are not required to achieve the desired effect, but make the code easier to read. If you need to support older browsers, you can use var instead of const, and a standard function instead of the fat arrow function.
3. Unfortunately—due to sandboxing—the Stack Overflow snippet feature does not work for this example, see this example on JSBin instead

If you want deep knowledge about it then try this article has more info: http://kb.mozillazine.org/Ui.key.contentAccess
If you find that you can't get used to the "in-tab" preferences dialog, there is a preference to return to the old style dialog:
In a new tab, type or paste about:config in the address bar and
press Enter. Click the button promising to be careful.
In the search box above the list, type or paste pref and pause while
the list is filtered
Double-click the browser.preferences.inContent preference to switch
it from true to false
Note: I don't know whether that will be in Firefox forever or is a transitional feature.

Related

Focus adress bar on page load [duplicate]

Desired behavior : When a Tabkey press happens on a particular dom element in a webPage I want my cursor focus to go to address bar.
(I want it via Javascript. Using any browser extension is not what is desired here)
When you press Control + L shortcut in a webpage, it takes your focus to address bar.
But when I try to trigger this via javascript it does'not work.
<div id="1" tabindex="1"></div>
<div id="2" tabindex="1"></div>
<div id="3" tabindex="1"></div>
<script>
var some = $('#1');
some.on('keydown', function (e) {
if (e.keyCode == 9 /* TabKey */) {
var e = jQuery.Event("keydown");
e.keyCode = 76 /* LKey */;
e.ctrlKey = true;
$('body').trigger(e);
}
});
</script>
Each browser (and operating system) handles this differently and it is not currently possible to highlight the address bar using javascript. Even if it was, keep in mind that people can map these commands differently (if they're not different already). For example, on a mac the command to access the address bar is Command + L, not Ctrl + L.
According to Trusted events in the UI Events specification
Events that are generated by the user agent, either as a result of user interaction, or as a direct result of changes to the DOM, are trusted by the user agent with privileges that are not afforded to events generated by script through the createEvent() method, modified using the initEvent() method, or dispatched via the dispatchEvent() method. The isTrusted attribute of trusted events has a value of true, while untrusted events have a isTrusted attribute value of false.
So triggering the CTRL+L event will have no effect on your browser which will need a trusted event for opening the address bar.
And yes, as already said by some people, removing default browser behaviour does not help accessibility.
On a purely technical point of view, jQuery UI gives you a very quick way for answering the use case in your comments. This will move to the last focusable element on "keydown", and then when you relapse the tab key, will go to the default element after your page (address bar, depending on your browser)
$("#MyLastElement").on('keydown', function (e) {
if((e.keyCode==9)&&(!e.shiftKey)) {
$(":tabbable").last().focus();
}
});

Javascript .`keypress` event not firing on mobile device

On this page:
https://subnetipv4.com/
If you click on any of the input boxes in the "IP Address" column, and press the "." or "/" keys (period or slash) it jumps you to the next input box.
Or at least, it does on a desktop browser. On a mobile browser, it doesn't seem to register the onkeypress event.
This is the code that is enabling the "jump" on period or slash presses:
// Function to jump to next box on . or / keys
function jumpdot(event) {
// Capture pressed key:
var y = event.key;
if (y == "." || y == "/" ) {
// . or / was pressed, jump to next userinput box and prevent typing of . or /
event.preventDefault();
document.getElementsByName(uiNext)[0].focus();
}
}
Is there an easy way to enable that functionality on Mobile phones as well?
edit: Updated website URL
The keypress event is marked as Legacy in the DOM-Level-3 Standard.
Warning. The keypress event type is defined in this specification for reference and completeness, but this specification deprecates the use of this event type.
Use the keydown event instead. Info: Keydown Event in Mozilla Developer
You should also consider ...
KeyboardEvent.which : Warning: This attribute is deprecated; you should use KeyboardEvent.key instead, if available.
KeyboardEvent.keyCode : Warning: This attribute is deprecated; you should use KeyboardEvent.key instead, if available.
To read the pressed Key , use instead event.key
ev.keyCode can be helpful. That provides more info about a keystroke.
Use oninput: instead of onkeypress:.

Unpreventable keyboard shortcuts in javascript

as the title suggests, I was wondering - what keyboard shortcuts cannot be prevented with javascript in modern browsers? Is this browser-dependent or even system-dependent?
So far, I've got Ctrl+N,Ctrl+Shift+N,Ctrl+T,Ctrl+Shift+T,Ctrl+W,Ctrl+Shift+W, all from Google Chrome. Then there's the standard windows shortcuts with the windows key like the windows key itself, winkey+R, winkey+S, etc., but also Ctrl+Shift+Escape. Is there any way to know what keyboard shortcuts will lead to something javascript can't prevent?
I suppose my question boils down to: if event is a keyboard event, then what does event.preventDefault(); actually prevent?
EDIT
Let's make a list here:
Ctrl+N
Ctrl+Shift+N
Ctrl+T
Ctrl+Shift+N
Ctrl+W
Ctrl+Shift+W
winkey + anything?
Ctrl+Shift+Escape
Ctrl+Alt-Delete (added by Psi)
Alt+F4
Escape and F11 (for fullscreen) (added by zer00ne)
You need to use capturing phase of events to handle and prevent it from default behaviour.
BUT! You cant override CTRL+R, CTRL+W or CMD events in safari.
Better way to prevent user for refreshing page is
window.onbeforeunload = function(event) {}
For example
function preventFn(event) {
if (event.keyCode === YOU_KEY_CODE && event.metaKey) {
event.preventDefault();
event.stopPropagation();
}
}
document.addEventListener('keydown', preventFn, true); // true means use capture phase of event
for example you can use high level library for shortcuts management
hotkeys - powerfull
stack-shortcuts - small and easy
p.s. instead of event.metaKey use what do you need. docs here

Capturing the TAB key in Gmail and other sites that blocks the capture

Using preventDefault() on a keydown works for all keys except the tab key on certain sites like Gmail.
Why is this the case? What is special about the tab key -- shouldn't it be treated the same as any other keypress?
How can I block the tab key from cycling through elements in Gmail?
Here is the Greasemonkey (JS with jQuery) code I'm currently using:
$("body.editable.LW-avf").keydown(function(event){
if(event.which == 9){
event.preventDefault();
}
});
Anything other than tab (e.g. a) works - the keypress is stopped. How can I capture the tab key?
Gmail is probably already using preventDefault to redefine the event handler, since it is not using tabindex. In that case, you would need to override the definition of preventDefault:
Event.prototype.preventDefault = function(){}

Javascript onChange arrow keys

Ok, so we all know that onChange is used to execute javascript code on a select statement when the option changes. However, if you change a select statement using the arrow keys, the onChange event is not called. Is there a way around this? Please help! I'm OCD I know.
--EDIT 1--
Just tested this in IE and arrow keys do work. Apparently it's just Chrome. ** Goes to check firefox
-- Edit 2 --
Tested in Firefox and realized just before an answer below talked about the onBlur action being required for the change. So the answer here is:
Internet Explorer recognizes onChange events from the keyboard as well as clicking on them.
Firefox and Chrome both require key events to be followed by blur event in order to call onChange.
Now normally, I don't like Internet Explorer, because it's a piece of garbage... But I think I... unfortunately, have to say they got that one right.
My understanding as to the reasoning for the blur event on chrome and firefox is to save resources, but I disagree with that. I feel it should follow the literal interpretation of the command onChange... Sigh... I suppose I'm probably wrong somehow, though.
I would suggest you to write the required code in Key Up event to capture the Key press and and also check for Key Code. Hope this helps
Scrolling through a select box is not considered a change. The change happens when you blur() the select and the new option value is applied to the select element.
Coming back to this, it appears that since the asking of this question, Chrome now fires onChange after key events. Firefox appears to still wait for onblur. http://jsfiddle.net/2aQBN/
$(document).ready(function() {
$("#test").on("change", function() {
console.log("Changed.");
});
});
W3C Specification appears to suggest using an input event instead.
When the input event applies, any time the user causes the element's
value to change, the user agent must queue a task to fire a simple
event that bubbles named input at the input element.
However, no input event appears to fire in Chrome or Firefox for the select element. (Just input elements.)
Test demonstrating the current value vs the last onchange value.
http://jsfiddle.net/teynon/MpyHK/5/
Firefox will change the value onmouseover. The key change will change the value as well. However, the onchange hasn't fired. If the form submits while the user has the select menu open, the currently highlighted option is submitted.
From W3C:
If the multiple attribute is absent, and the element is not disabled,
then the user agent should allow the user to pick an option element in
its list of options that is itself not disabled. Upon this option
element being picked (either through a click, or through unfocusing
the element after changing its value, or through a menu command, or
through any other mechanism), and before the relevant user interaction
event is queued (e.g. before the click event), the user agent must set
the selectedness of the picked option element to true and then queue a
task to fire a simple event that bubbles named change at the select
element, using the user interaction task source as the task source.
There is a LONG discussion at https://bugzilla.mozilla.org/show_bug.cgi?id=126379 about this with many people asking for the arrow keys to work. (And some defending the onchange approach.)
Some users have suggested that the W3C is flat out wrong in the specification for the select element's change event. Instead suggesting we propose changes to the specification for how we expect the select's onchange functionality to work.
The current functionality is clearly not intuitive to a large number of people based solely on the number of bug reports. (Mozilla has 40 marked as duplicates.)
This is a pretty dirty hack, but you can force the the change event to fire by doing this:
element.addEventListener('keyup', function(evt){
evt.target.blur();
evt.target.focus();
}, false);
So you'd register an event listener for change as well, and that function would get called when the user presses a key on the <select> via the code above.
You may want to scope this only to Firefox, but AFAIK you'd have to use UA sniffing for that so it's up to you if that's acceptable.
Source
I'm thinking about something like this (to not trigger event if value wasn't changed):
select.keydown(function(){
var _this = $(this);
var _val = $(this).val();
setTimeout(function(){
if(_this.val() !== _val){
_this.trigger("change");
}
}, 1);
});
Here's a realization of this request. For brevity only showing the code. See https://github.com/ida/skriptz/blob/master/js/fields/select/selection_changed.js for long explanations in comments.
function addSelectionChangedListener(selectionEle, onChangeDoWithEle) {
var selectedIndex = null
function onChangeEvent(eve) {
// If selection-change was caused of an option's click-event:
if(eve.explicitOriginalTarget.tagName.toLowerCase() == 'option') {
// We want to trigger passed event-handler:
onChangeDoWithEle(eve.target)
}
}
function onKeyEvent(eve) {
// Key-event is keydown, remember current selectedIndex:
if(eve.type == 'keydown') {
selectedIndex = eve.target.selectedIndex
}
// Key-event is keyup, if selection changed, trigger passed handler:
else if(selectedIndex != eve.target.selectedIndex) {
onChangeDoWithEle(eve.target)
}
}
selectionEle.onchange = function(eve) onChangeEvent(eve)
selectionEle.onkeydown = function(eve) onKeyEvent(eve)
selectionEle.onkeyup = function(eve) onKeyEvent(eve)
}

Categories

Resources