Is there a way change an event and let it propagate further with the change?
For example how can I "force" press shift
when any key is pressed?
window.focus();
window.addEventListener("keypress", e =>
{
//force shift key doesn't work
e.shiftKey = true;
})
window.addEventListener("keypress", e =>
{
console.log("shift", e.shiftKey);
});
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
(this is just an example, I'm looking for a general solution that would work with any type of event)
CodePudding user response:
Use strict mode to see why your code isn't working:
'use strict';
window.focus();
window.addEventListener("keypress", e =>
{
//force shift key doesn't work
e.shiftKey = true;
})
window.addEventListener("keypress", e =>
{
console.log("shift", e.shiftKey);
});
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
The event that the browser passes to addEventListener
(regardless of propagation status) can't have certain intrinsic properties changed, including shiftKey
. While you could assign to a different non-reserved property of the event, a better approach I think would be to use a WeakMap that maps the event to the new propert(ies) you want.
'use strict';
const customPropertiesByEvent = new WeakMap();
window.focus();
window.addEventListener("keypress", e =>
{
customPropertiesByEvent.set(e, { shift: true });
})
window.addEventListener("keypress", e =>
{
console.log("shift", customPropertiesByEvent.get(e).shift);
});
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You can't "change" a KeyboardEvent. It's read-only.
It took a while, but apparently it IS the same object that gets passed to all the event listeners.. I messed with the get
properties of Event
and KeyboardEvent
and the edited event passes smoothly :D
window.focus();
function control(event){
if(typeof event=='function'){event=event.prototype}
let properties=Object.getOwnPropertyDescriptors(event)
Object.keys(properties)
.filter(key=>
!Object.keys(properties[key]).includes('value')
)
.forEach(key=>{
const original=properties[key].get
var value=null, valueSet=false
function set(something){
value=something; valueSet=true
}
function get(){
return valueSet?value:original.call(this)
}
properties[key]={...properties[key],get,set}
})
Object.defineProperties(event,properties)
}
//for any event class given to it, this function makes its prototype functions malleable
control(KeyboardEvent); control(Event)
//not all but A LOT of the prototypes including shiftKey fall under these 2 classes
//eventListener that I assume you control and add first
window.addEventListener("keypress", e =>
{
e.shiftKey=true //your edit to the event
})
//event listener that might be in the environment that you didn't make
window.addEventListener("keypress", e =>
{
console.log("shift", e.shiftKey);
});
console.log("press an unshifted letter in this area")
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>