React event propagating in the else case - javascript

let's say I have a function that gets executed on key press that looks like something like this. I want to have special case for when Enter is pressed otherwise I want even to propogate/bubble up to the browser. Therefore, if any other key is pressed this i.e up or down arrows they should work.
onAutosuggestInputKeyDown = event => {
if (event.key === 'Enter') {
this.onCustomSuggestionCreate(event)
} else {
// keep propgating the event
}
}
getAutosuggestInputProps = () => {
return {
inputProps: {
onBlur: this.onCustomSuggestionCreate,
onKeyDown: this.onAutosuggestInputKeyDown,
},
}
}
<ReactAutoSuggest textFieldProps={this.getAutosuggestInputProps()}/>

If I understand your situation correctly, then even propagation should occour by default (depending on the type of element that fired the event).
You would however, likely want to use stopPropagation() in the case of the enter key being pressed to prevent the propagation of that event, which would be achieved by the following update to your onAutosuggestInputKeyDown method:
onAutosuggestInputKeyDown = event => {
if (event.key === 'Enter') {
// Prevent this event from propagating if enter key pressed
event.stopPropagation()
this.onCustomSuggestionCreate(event)
}
// If stopPropagation() not called on event, the event will propagate
// if it has the ability to do so (ie from the element dispatching the
// event)
}

Related

react js, trying to remove a nested event listener

I'm trying to create a game and the goal currently is do draw a line (narrow div) from player position to mouse hovering position, so that the line displays the trajectory of ability, like in diablo games or modern moba's, but only when left click is held down.
Currently I listen for mouse down and mouse up and add or remove classes when I need to.
But now I need to make it so that while the left click is pressed, I need to get mousemove coordinates.
My code assigns mouse move listener when the left click is down, but I can't remove the mousemove listener when the left click is up
function detectLeftButton(event) {
if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) {
return false;
} else if ('buttons' in event) {
return event.buttons === 1;
} else if ('which' in event) {
return event.which === 1;
} else {
return (event.button === 1 || event.type === 'click');
}
try {
map.addEventListener('mousedown', (event) => {
if (detectLeftButton(event) === true) {
handleMouseDown();
map.onmousemove = handleMouseMove();
map.addEventListener('mouseup', () => {
handleMouseUp();
map.onmousemove = null;
});
}
})
}
catch(err) {
}
Although I'm not 100% sure why setting onmousemove to null doesn't work, I can say that you can use removeEventListener in order to detach an event handler from the event. For this to work, you have to pass a reference to the function you're trying to remove to both addEventListener and removeEventListener. Also, the way you've written the code, you're not clearing your mouseUp event handler, which means it may end up getting invoked more times than you want.
Inside the try/catch block take this for a spin:
map.addEventListener('mousedown', (event) => {
if (detectLeftButton(event) === true) {
handleMouseDown();
map.addEventListener('mousemove', handleMouseMove);
}
})
map.addEventListener('mouseup', (event) => {
handleMouseUp();
map.removeEventListener('mousemove', handleMouseMove);
})
Another option would be to have some kind of state variable that you set in mousedown/mouseup that allows a mouse move handler to determine whether or not to take action. Then you may not need to worry about detaching the event (although I don't know enough about your solution to say for sure). You can find an example of this type of solution on MDN: https://developer.mozilla.org/en-US/docs/Web/API/Element/mousemove_event

How to detect if the event that is generated belongs to Keyboard, Pointer or Form Event?

I have developing an application that records the events and replays them. For that I need to identify what kind of event is being generated because mouse, keyboard and form events behave differently from each other.
Right now i am trying to use:
e instanceof KeyboardEvent but this doesn't seems to be working. What is the better way of identifying to which event family it belongs to?
A basic example for a mouse and keyboard event. You just have to add an eventListener to your desired dom element. And then you have to check if the triggered event e is an instance of MouseEvent or if it is a KeyboardEvent.
const button = document.getElementById('mouse');
button.addEventListener('mousedown', (e) => {
if (e instanceof MouseEvent) {
console.log('a mouse event');
}
});
const inputField = document.getElementById('keyboard');
inputField.addEventListener('keydown', (e) => {
if (e instanceof KeyboardEvent) {
console.log('a keyboard event');
}
});
<button id="mouse">MouseButton</button>
<input id="keyboard">
Using the event.detail allow you to determine if the event was a keypress or mouse event
if (event.detail === 0) {
// keypress event
} else {
// mouse event
}
Read more here - https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail

Call setState with Click or Escape Key

I have a React Modal that opens and closes via a handler function.
I'd like to call that function with either a click event or with the use of the esc key for accessibility proposes.
How could I track both events at the same time?
So far I got the esc event as:
handleCloseModal = event => {
if (event.keyCode === 27) {
this.setState({ modal: false })
}
}
But then I lose the click functionality on
<Modal
onClick={handleCloseModal}
role="button" tabIndex={0}
onKeyDown={handleCloseModal}
/>
How should I go about this?
One possible solution can be: Create a separate function to close the Modal. Use that function for onClick and call it when esc key pressed.
Like this:
<Modal
onClick={handleCloseModal}
role="button" tabIndex={0}
onKeyDown={handleKeyDown}
/>
handleKeyDown = event => {
if (event.keyCode === 27) {
handleCloseModal()
}
}
handleCloseModal = () => this.setState({ modal: false })
If I understand correctly, you're wanting to reuse the same close event handler for both click and keydown event types. One way to distinguish between these two event types would be to detect the event object's type via instanceof as follows:
handleCloseModal = event => {
// if event is mouse event, handle it accordingly
if(event instanceof MouseEvent) {
// if mouse click detected hide the modal
this.setState({ modal: false })
}
// if event is keyboard event, handle it accordingly
else if(event instanceof KeyboardEvent) {
// if escape key pressed for keyboard event then hide the modal
if (event.keyCode === 27) {
this.setState({ modal: false })
}
}
}

How to disable hotkeys when inputting?

When the user presses a certain key, a component shows. I have four such components. When the user is typing or editing, I want to disable the hotkeys.
I have this code in each of the four components
componentDidMount(){
document.body.addEventListener("keypress", (e) => {
if (e.key === "t") { // "n" "w" "," for the others
this.setState({opened: !this.state.opened});
}
});
}
I only want to disable hotkeys when the user is typing or editing. Is there a way to know if any input is in focus? Or the other way, can we add the event listeners only if all the inputs are 'on blur'?
So we need to know if any of the inputs on the page are in focus and if any of them is focused then we just will not do anything to show or hide components.
Let's assume that our component has in the state some property which indicates that some input on the page is focused, let's call it isFocus.
So, we need to collect all inputs on the page, iterate over them all and assign to each input the focus and the blur event handlers, so we will be able to know when to change the isFocus property in the state.
First of all, we need to collect all of the inputs on the page, we do it with:
const inputs = document.getElementsByTagName('input').
Iterate over them all and assign the focus and blur event handlers:
for (let input of inputs) {
input.addEventListener('focus', () => this.setState({isFocus: true}));
input.addEventListener('blur', () => this.setState({isFocus: false}));
}
And finally, let's change the condition for the keypress event:
document.addEventListener('keypress', e => {
if (!this.state.isFocus && e.key === "t") {
this.setState({opened: !this.state.opened});
}
});
Everything together will look like this:
componentDidMount() {
const inputs = document.getElementsByTagName('input');
for (let input of inputs) {
input.addEventListener('focus', () => this.setState({isFocus: true}));
input.addEventListener('blur', () => this.setState({isFocus: false}));
}
document.addEventListener('keypress', e => {
if (!this.state.isFocus && e.key === "t") {
this.setState({opened: !this.state.opened});
}
});
}
Hope this helps. Good luck.
You could move the current open component state to the most upward component, like the following:
state: {
openComponent: null
}
your hotkey function would look like this:
hotkey(e){
const componentKeyHandlers = {
"n": {openComponent: "componentN"},
"m": {openComponent: "componentM"}
}
if (e.keyCode === 27) { //ESC
this.setState({openComponent: null});
} else if (!this.state.openComponent) {
this.setState(componentKeyHandlers[e.key]);
}
}
I'm assuming you could only have ONE open component each time. Also, you could close them by hitting ESC.
For each component, its visibility would be controlled by comparing props.openComponent to its name, given that the current state component is passed down to each one via props.
This way you don't need to unregister the hotkey function. When you start typing with an open component, the setState is going to be ignored due to the if (!this.state.openComponent) condition.

Prevent menu key from showing a context menu

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.

Categories