Reputation: 10221
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);
});
(this is just an example, I'm looking for a general solution that would work with any type of event)
Upvotes: 4
Views: 556
Reputation: 4337
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){
const eventMap=new WeakMap()
const getMap=(instance,key)=>{
let map=eventMap.get(instance)
if(!map){
map={[key]:{value:null,valueSet:false}}
eventMap.set(instance,map)
}
if(!map[key]){map[key]={value:null,valueSet:false}}
return map[key] //specific to an event instance AND key
}
if(typeof event=='function'){event=event.prototype}
let properties=Object.getOwnPropertyDescriptors(event)
Object.keys(properties)
.filter(key=>
typeof(properties[key].get)=='function'
)
.forEach(key=>{
const original=properties[key].get
function set(something){
let map=getMap(this,key)
map.value=something; map.valueSet=true
}
function get(){
let {value,valueSet}=getMap(this,key)
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=!e.shiftKey //your edit to the event(switches the shiftKey event locally and not globally)
})
//event listener that might be in the environment that you didn't make
window.addEventListener("keypress", e =>
{
console.log("shift", e.shiftKey); //false when u use shift, true when u don't use shift now >:D
});
console.log("press an unshifted letter in this area")
@vanoworm, for your electron app.. here's a working example of an event edit working smoothly
EDIT I saw your response
basically it changes
shiftKey
property globally for all future events, not only for current one.
Thank you for telling me.. I just fixed that and also.. about control.js
, it can just be a string on your backend since it's meant to execute on the browser ;-; my bad
index.js
var control=require('./control.js')
const {BrowserWindow,app} = require('electron')
app.on('ready',()=>{
const win = new BrowserWindow({ width: 800, height: 600 })
let script=control+'\ncontrol(Event); control(KeyboardEvent)\n'
+'window.addEventListener("keypress",e=>e.shiftKey=true)\n'
+'window.addEventListener("keypress",e=>console.log(e.shiftKey))\n'
+'console.log("press an unshifted letter in this browser")'
win.webContents.executeJavaScript(script)
win.loadURL('https://github.com')
})
control.js
module.exports=`
function control(event){
const eventMap=new WeakMap()
const getMap=(instance,key)=>{
let map=eventMap.get(instance)
if(!map){
map={[key]:{value:null,valueSet:false}}
eventMap.set(instance,map)
}
if(!map[key]){map[key]={value:null,valueSet:false}}
return map[key] //specific to an event instance AND key
}
if(typeof event=='function'){event=event.prototype}
let properties=Object.getOwnPropertyDescriptors(event)
Object.keys(properties)
.filter(key=>
typeof(properties[key].get)=='function'
)
.forEach(key=>{
const original=properties[key].get
function set(something){
let map=getMap(this,key)
map.value=something; map.valueSet=true
}
function get(){
let {value,valueSet}=getMap(this,key)
return valueSet? value: original.call(this)
}
properties[key]={...properties[key],get,set}
})
Object.defineProperties(event,properties)
}
`
Upvotes: 1
Reputation: 370999
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);
});
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);
});
Upvotes: 1