Prevent menu key from showing a context menu - javascript

I know that the keyboard menu key is keyCode === 93.
So I have the following code:
$(window).on("keydown", document, function(event){
if (event.keyCode === 93) { //context menu
console.log("context menu key", event);
event.preventDefault();
event.stopPropagation();
return false;
}
});
Although the event does fire, and the console does get logged inside the if statement, but the context menu still shows even though both event.preventDefault(); and event.stopPropagation(); are present in my code.
Is there any way to prevent the menu from being displayed?
Demo for fiddling: http://jsfiddle.net/maniator/XJtpc/
For those of you who do not know what the "menu" key is:

This is kind of dumb but it seems to work: http://jsfiddle.net/XJtpc/2/ :)
$(function(){
var lastKey=0;
$(window).on("keydown", document, function(event){
lastKey = event.keyCode;
});
$(window).on("contextmenu", document, function(event){
if (lastKey === 93){
lastKey=0;
event.preventDefault();
event.stopPropagation();
return false;
}
});
});
​

I started with #aquinas' solution but discovered it can be a bit simpler than that.
Steps
Register keydown event handler. e.preventDefault not required.
Register contextmenu event handler and just do e.preventDefault()
Example:
// JavaScript
// Register your `ContextMenu` key event handler
document.querySelector('body').onkeydown = (e) => {
if (e.key === 'ContextMenu') {
// Do something
}
}
// Prevent `contextmenu` event default action
document.querySelector('body').oncontextmenu = (e) => e.preventDefault();
// jQuery
// Register your `ContextMenu` key event handler
$('body').on('keydown', (e) => {
if (e.key === 'ContextMenu') {
// Do something
}
});
// Prevent `contextmenu` event default action
$('body').on('contextmenu', (e) => e.preventDefault());

The trick is that it's the keyup event, not the keydown event that triggers the context menu. Calling .preventDefault() on a keyup event whose .key is ContextMenu will stop it from happening, at least in Chrome and Electron.
That is, you can globally disable the context menu key just with:
window.addEventListener("keyup", function(event){
if (event.key === "ContextMenu") event.preventDefault();
}, {capture: true})
And then monitor the keydown event to trigger your replacement.

Related

Is there any way to revert preventDefault method in Vanilla JavaScript?

I'm trying to create a horizontal scrolling container. In a precise case i need to revert e.preventDefault(); from a click.
I tried a lot of options, changing 'window.location.href' in the else statement seems to be a great option.
But i can't figure how to grab the href from the link clicked.
Any idea can help to achieve my goal. :)
slider.addEventListener('mouseup', () => {
isDown = false;
// Disable click event (for ever unfortunately)
if(moved === true) {
this.addEventListener('click', (e) => {
e.preventDefault();
});
} else {
// trying to reset click function
}
You can conditionally prevent a click event from firing on your slider by registering a click event listener that shares the moved variable with your mousedown and mousemove event listeners.
The { passive: true } option indicates that the listener does not call event.preventDefault(), and saves a lot CPU time particularly for the mousemove event which can fire several times per second.
The true parameter indicates that the event listener should be called before the event starts to bubble up from the target element. This allows it to prevent propagation even to listeners that were already added on the same element, as long as they didn't also set useCapture to true.
const slider = document.querySelector('input[type="range"]');
// prevent this if mousemove occurred between mousedown and mouseup
slider.addEventListener('click', () => {
console.log('click event fired on slider');
});
// fires just before click event
slider.addEventListener('mouseup', () => {
console.log('mouseup event fired on slider');
});
let moved = false;
// reset for each potential click
slider.addEventListener('mousedown', () => {
moved = false;
});
// indicate cancellation should occur for click
slider.addEventListener('mousemove', () => {
moved = true;
}, { passive: true });
// prevents click event if mousemove occurred between mousedown and mouseup
slider.addEventListener('click', event => {
if (moved) {
event.preventDefault();
event.stopImmediatePropagation();
}
}, true);
<input type="range" />
You should remove the event listener containing the event.preventDefault();.
In order to do that you have to save your function reference into a variable like so:
const preventClickHandler = (e) => e.preventDefault;
slider.addEventListener('mouseup', () => {
isDown = false;
// Disable click event (for ever unfortunately)
if(moved === true) {
this.addEventListener('click', preventClickHandler);
} else {
this.removeEventListener('click', preventClickHandler);
}
})

How to correctly handle right click mouse event for a button

I want to handle mouse right-click event for my button. I wrote the following code;
mybutton.onmousedown = e => {
e.preventDefault();
const mouseEvent = {
0: () => leftClickCallback,
2: () => rightClickCallback
}
mouseEvent[ e.button ]();
}
It works fine but it doesn't prevent the browser context menu and I have to set the "oncontextmenu" event like below to prevent the browser context menu event;
mybutton.oncontextmenu = e => e.preventDefault();
I've also tried to stop propagation of mouse event like below although it didn't work:
mybutton.onmousedown = e => {
e.preventDefault();
e.stopPropagation(); // <====
const mouseEvent = {
0: () => leftClickCallback,
2: () => rightClickCallback
}
mouseEvent[ e.button ]();
}
I am wondring why I need to explicitly disable oncontextmenu event for my button.
The right mouse button click seems to fire multiple events (though it might depend on the browser) :
a MouseDown event, with event.button === 2 and/or event.which === 3,
a ContextMenu event.
It makes sense since the context menu can also be opened by a keyboard button (depending on your keyboard layout), or a macro.
What you can do is use the same callback. For example :
function preventAll(event) {
event.preventDefault();
event.stopPropagation();
}
document.getElementById('something').addEventListener('mousedown', preventAll);
document.getElementById('something').addEventListener('contextmenu', preventAll);
<button id="something">test</button>

Understanding how many times the jquery events are called and right handling of keyup event

I am trying to develop my webpage where I have a simple input field where I can type something. I want that when I type something and press "enter", a function gets called. The code I am using is:
$(document).ready(function(){
$("#searchBar").click(function(){
$("#searchBar").keyup(function (e) {
if (e.keyCode == 13) {
$(this).trigger("enterKey");
}
});
$("#searchBar").bind("enterKey", function (e) {
searchFunction();
});
})
})
Something is not working well. I have 2 questions:
First of all by debugging on the browser I realize that the event "keyup" is called whenever I type any kind of character, but not when I press "enter" and I don't know why.
By always debugging and using a breakpoint on the keyup handler, it happens that when I press a key, in order to get out from the breakpoint I have to resume the script execution once.. then if I type another character and I go again at the breakpoint, I have to resume the script exectuion twice instead of once to continue debugging.. and so on incresing.. why do I have this kind of behavior?
Thanks in advance!
Two problems:
#searchBar only listens to keyUp and Enter if you have clicked on it at least once
#searchBar adds a new keyUp and Enter listener for each time it receives a click event
I'd just bind the events once like so:
$(document).ready(function(){
$("#searchBar").keyup(function (e) {
if (e.keyCode == 13) {
$(this).trigger("enterKey");
}
});
$("#searchBar").bind("enterKey", function (e) {
searchFunction();
});
});
I can't come up with a valid reason to stop listening to the events, but if that's what you want, then I'd unbind just before or after the call to your searchFunction();
$(document).ready(function(){
$("#searchBar").click(function(e){
$(this).keyup(function (e) {
if (e.keyCode == 13) {
$(this).trigger("enterKey");
}
});
$(this).bind("enterKey", function (e) {
searchFunction();
$(this).unbind("enterKey");
$(this).unbind("keyup");
});
});
// but you'd also need to unbind the events if the user clicks somewhere else in the document, otherwise, these events would still get attached every time the user clicks #searchBar
});
But it's unnecessary, as the events are only fired when #searchBar has focus. All these events also detach if you delete #searchBar
Also, why fire "enterKey" when you already are listening for keystrokes?
$(document).ready(function(){
$("#searchBar").keyup(function (event) {
var keycode = event.keyCode || event.which; //this for cross-browser compatibility
if (keycode == 13) {
searchFunction();
}
});
});
I have to resume the script exectuion twice instead of once to
continue debugging.. and so on incresing.. why do I have this kind of
behavior?
You are attaching a new keyup and enterKey event at each click on element.
Remove click event or use .one() to attach click event
$(document).ready(function() {
var search = $("#searchBar").keyup(function (e) {
if (e.keyCode == 13) {
search.trigger("enterKey");
}
})
.on("enterKey", function (e) {
searchFunction();
});
})
or, if one click is intended to begin process
$(document).ready(function(){
var search = $("#searchBar").one("click", function() {
search.keyup(function (e) {
if (e.keyCode == 13) {
search.trigger("enterKey");
}
})
.on("enterKey", function (e) {
searchFunction();
});
})
})

How to prevent a "keypress" event firing a "click" event when focus is on a button - javascript/html dom

I have a button that fires a "stopstart" function (animation). I also want to have a mouseless method to do this so I've bound the same function to the space bar. This works.
However if focus is on the button, and I press space - both events fire, can't work out how to stop this (the keypress event fires first - in chrome..)
Eventlistener code:
document.getElementById("stopstart").addEventListener("click",
function (event) {
stopstart();
}); //add event listener to "stopstart" button
document.addEventListener("keypress",
function (event) {
if (event.keyCode === 32) { //space key
stopstart();
}
}); //add spacekey event listener to document
I don't want to remove focus from the button, as I'd like to retain that functionality - the two events appear to be separately generated - so I haven't found how to detect that the click event was in fact generated by the space bar.
Is this solvable using without having to add temporary flags to catch it etc
The click location for key events is zero, zero so you can look for that.
document.getElementById("stopstart").addEventListener("click",
function (event) {
var x = event.x || event.clientX;
var y = event.y || event.clientY;
if (!x && !y) {
alert("key press");
return false;
}
stopstart();
});
http://jsfiddle.net/mScEC/
function (event) {
if (event.pointerType !== "mouse") return;
stopstart();
}); //add event listener to "stopstart" button
document.addEventListener("keypress",
function (event) {
if (event.keyCode === 32) { //space key
stopstart();
}
}); //add spacekey event listener to document```
You can simply use event.preventDefault() inside keypress event Listener to prevent the Button Click event from getting triggered on keypress
e.g
document.addEventListener('keydown', function (e) {
e.preventDefault();
if (e.key === 'Enter') {
try {
// if expression is not evaluated then catch block will be executed
screen.value = eval(screen.value);
}
catch (error) {
console.log(error.message);
screen.value = 'Invalid Operation';
}
}
})

Avoid multiple event listeners from .focus

I currently have a textbox that I am invoking a keyboard stroke on focus:
$myTextBox.on('focus', function(e){
$(document).keydown(function(e){
if(e.which==13)
e.preventDefault()
});
$(document).keyup(function(e){
if(e.which ==13)
alert("hey");
});
});
If I click on this multiple times pressing 'enter' once will cause many alerts, how can I avoid this so that only it is only invoked once.
You're adding the event listener every time the field gets focus.
Just add the keydown, keyup listener on the document ready function...
$(function() {
$("#myTextBox").keydown(function(e){
if(e.which==13)
e.preventDefault()
});
$("#myTextBox").keyup(function(e){
if(e.which ==13)
alert("hey");
});
});​
http://jsfiddle.net/ShHkP/
Like others have said, you don't have to keep adding the event on focus. As well, you should just attach the event to the textbox itself because that is in fact what you're trying to do when you add the event on focus.
$myTextBox.on({
'keydown': keyDown,
'keyup': keyUp
});​
So that your application doesn't go into an enter-alert-ok loop, you have to turn off the keyup listener before the alert() call, and then turn it back on after hitting ok.
Here's a fiddle.
I see what you're trying to do (or not?). You could just attach the event to the form and exclude the textarea instead of adding it to the document everytime the input gets focused.
$('form').on('keydown', function( e ) {
// Prevent submit when pressing enter but exclude textareas
if ( e.which == 13 && e.target.nodeName != 'TEXTAREA' ) {
e.preventDefault();
}
}
var alreadyPressed = false;
$("textarea").keypress(function (e) {
if (e.which == 13) {
e.preventDefault();
alreadyPressed = true
}
});
$("textarea").keyup(function (e) {
if (e.which == 13 && !alreadyPressed) {
alert("hey");
alreadyPressed = false;
}
});
http://jsfiddle.net/DerekL/Dr6t2/

Categories