I would like to switch between pages using arrows (37 - left arrow, 39 - right arrow). The code below works correctly with Firefox, Chrome and Internet Explorer.
The solution does not work with Microsoft Edge after Back (back in browsing history) button has been clicked in the browser. Does anybody know how to fix it?
<script type="text/javascript">
window.addEventListener("keydown", checkKeyPressed, false);
function checkKeyPressed(event) {
var x = event.which || event.keyCode;
if (x == 37) { window.location.href = "page1.html";}
if (x == 39) { window.location.href = "page2.html";}
};
</script>
This looks like a bug. In that when you use the navigation controls (or the refresh button) the window seems to lose focus and so keydown events do not fire. Also window.focus doesn't seem to work as expected either.
But I have found a workaround (or two). The first is to modify your script to look like this:
<script>
window.onload = function(){
document.body.focus();
document.addEventListener("keydown", checkKeyPressed, false);
function checkKeyPressed(event) {
var x = event.which || event.keyCode;
if (x == 37) { window.location.href = "page1.html"; }
if (x == 39) { window.location.href = "page2.html"; }
};
}
</script>
You then need to add a tab index to the body tag e.g:
<body tabindex="1">
This then allows you to programmatically set the focus of the page (And it isn't ignored by Microsoft Edge like window.focus() is) The reason you need to add tabindex to the body is because the focus method is implicitly applicable to a limited set of elements, chiefly form and <a href> tags. In recent browser versions, the event can be extended to include all element types by explicitly setting the element's tabindex property.
This workaround does add a potential accessibility issue since your element can gain focus via keyboard commands, such as the Tab key. Although I'm not sure how much of a problem that really is.
The second option is to add a form element to your page and either manually set focus to it or add the autofocus attribute:
<input autofocus>
Edge seems to respect this and gives the element auto focus and your key down events will now fire. Sadly You can't just hide this element, since if it's hidden it no longer get auto focus. (maybe you could set it's opacity to 0) but I didn't try.
Of the two options I prefer workaround 1. I will file this as a bug with the Edge team on connect when I get a chance this afternoon.
Related
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
I have to manually set the caret-position to 0 in an input-field (in the input-event). I need to support >= IE9. Even in IE9 this works ok as long as I do normal input (pressing keys on my keyboard). But as soon as I use copy&paste, the caret isn't set to the desired position (0).
Steps to reproduce:
Open IE in IE9-Mode
Open fiddle below
Type into the input-field (works ok, the caret gets set to 0)
Paste something into the input-field (fails, the caret gets set to the end of the pasted text)
Fiddle: https://jsfiddle.net/wv61t7k5/7/
Code
<input type="text" />
document.querySelector('input').addEventListener('input', function(){
this.setSelectionRange(0,0);
});
Funny. First I thought IE9 maybe would not fire the event on pasting, but it does. No idea why this would not work.
However, you could use the keyup event. This is definitely not as good as using input but will work in IE9.
document.querySelector('input').addEventListener('keyup', function(e){
if (e.key != 'Left' && e.key != 'Right' &&
e.key != 'Shift' && e.key != 'Control') {
this.setSelectionRange(0,0);
}
});
To still be able to select text by keyboard, you'd have to exclude some keys.
Here is an updated Fiddle.
Update
Well, this still does not work if the user pastes text by using mouse and context menu. Happily IE knows the paste event. Unhappily there is no after paste event, so you'd end up using a timeout:
document.querySelector('input').addEventListener('input', function(e){
this.setSelectionRange(0,0);
});
document.querySelector('input').addEventListener('paste', function() {
var that = this;
setTimeout(function() {
that.setSelectionRange(0,0);
}, 100);
});
Here is a Fiddle.
I've been looking for a way to activate my "off-canvas" navigation when I press the "M" key.
I'll be more specific, I want my "off-canvas" navigation to slide in or out when I press the "M" key on my keyboard.
I already have the basic functionality of my "off-canvas" navigation worked out. I'm just stuck on the keypress thing.
Thanks!
I've had good experiences with the Mousetrap plugin. With it you can easily bind keypresses/combinations and execute code with it. It, among other things, automatically handles whether an input is focused (in which case you wouldn't want to execute the keybind)
Without having seen your code, I'm guessing by offcanvas navigation you mean the navigation menu you see in mobile pages, opened by pressing a button?
In which case you could use the following:
Mousetrap.bind('m', function() {
$("#your_menu_toggle_button").trigger("click");
});
If you donĀ“t care about which element has the focus you can bind an event-handler to the window
// Jquery:
$(window).on('keypress', callBack);
// JS:
window.onkeypress = callBack;
and check for the key (http://www.mediaevent.de/javascript/onkeydown.html)
var callBack = function(event){
// checking for 'm' and 'M' cross-Browser compatible
var pressedM = (event.keyCode == 77 || event.keyCode == 109
|| event.which == 77 || event.keyCode == 109)
if (pressedM){
/* logic here */
}
}
Then you need to define, how to activate your navigation and how to deactivate.
Your talking about sliding it in, so I assume you want to use something like JQuerys slideToggle() functionality for now:
...
/* logic here */
$('#offCanvasNav').animate({height: 'toggle'});
// same as .slideToggle() change height for width for sideways slide
jquery .slideToggle() horizontal alternative? - http://jsfiddle.net/7ZBQa/
I have an application that does something (eg alert) each time a spacebar is pressed. This works fine if I am not using JAWS screen reader. However, once I load JAWS screen reader, it does not execute alert when I press the spacebar. I need to use JAWS so I need this to work. Here is the code snippet.
$(document).keypress(function(event) {
var chCode = ('charCode' in event) ? event.charCode : event.keyCode;
if (chCode == 32){ //32 is keyCode for spacebar
alert("spacebars!!!");
}
});
From my observation, it seems JAWS grabs the keyboard focus and wouldn't allow the spacebar event to fire. JAWS always reads "Space" when I press the spacebar but the alert event does not fire. How can I still get the alert or doSomething() to fire when the spacebar is pressed? How can I take control from JAWS or maybe share keyboard control with JAWS such that even though JAWS reads out the character I pressed (in this case Spacebar), it will allow my event (alert) to fire. Thanks.
More code:
$(document).keypress(function(event) {
var cc= ('charCode' in event) ? event.charCode : event.keyCode;
if (cc == 32)
{
spArray.push(Number(new Date()));
}
});
In general, it is not advisable to over-ride screen readers, even if they let you. There are quite a few JAWs keyboard commands (in conjunction with INS) that use the spacebar, and you'd probably lock those commands out.
If the area is primarily formed controls or interactive widgets then you could wrap it in an element with role="application". That puts a (windows) screen reader into 'forms' mode, where keys are passed through to the web-page.
Do not wrap everything in role="application", just the interactive area.
Update: With more information, this is about an audio-based capture where the user triggers an audio file, then triggers something again to set a time and pass the capture.
Using a native button, Jaws will pass through the use of enter (not sure about space, that isn't the usual 'activate' key). I'd suggest either checking for enter key (charcode 13 I think), or even onclick should work. On a native button/link it works across screen readers.
$(document).click(function() {
spArray.push(Number(new Date()));
});
Assuming that's in the right location so that it doesn't become active until needed. (JS isn't my strong point, but go with the enter key or onclick.
An event handler declared like this works in our application:
doKeyDown_: function (evt) {
var key = evt.keyCode || evt.which;
//arrows
if (key == 27 || (key >= 37 && key <= 40)) {
try {
if (key >= 37 && key <= 40) {
this.handleArrwos(evt);
} else {
this.handleEsc(evt);
}
...
Although it is based on the ZK platform, the inner engine is still JQuery. Please note that the event is keyDown (not keyPress) and how the pressed key is detected. The example is for Esc and arrow keys - Space should be no problem.
As for accessibility, our etire page is declared as role="application", since the entire content is a dynamically generated page, it's really an application. Only this way Jaws doesn't eat up about any possible keys combination.
I am making an HTML 5 game which requires the use of right click to control the player.
I have been able to disable the right click context menu by doing:
<body oncontextmenu="return(false);">
Then it came to my attention that if you hold shift and right click, a context menu still opens in Firefox!
So I disabled that by adding this JS as well:
document.onclick = function(e) { if(e.button == 2 || e.button == 3) { e.preventDefault(); e.stopPropagation(); return(false); } };
However, if you hold shift, and then double right click in Firefox it still opens!
Please tell me how to disable this bloody thing once and for all (I'm even willing to revert to some obscure, hacky, and unpractical solution, as long as it works).
You will never be able to entirely disable the context menu in all cases, as firefox has a setting that allows the user to tell the browser to ignore such hijinx as you are trying to pull.
Note: I'm on a mac, but this setting is in pretty uch the same place over all platforms.
That being said, try event.preventDefault() (see Vikash Madhow's comment on this other SO question:
How to disable right-click context-menu in javascript)
There is actually example in official documentation that blocks directly context menu event:
document.oncontextmenu = function () { // Use document as opposed to window for IE8 compatibility
return false;
};
window.addEventListener('contextmenu', function (e) { // Not compatible with IE < 9
e.preventDefault();
}, false);
document.ondblclick = function(e) {
if(e.button == 2 || e.button == 3) {
e.preventDefault();
e.stopPropagation();
return(false);
}
};