Mouse click simulates keyboard key in JavaScript - javascript

I have situation that in application (HTML/XUL) there are key bindings for some function keys (F5, F7 & F9) in order to communicate with some other application.
Now I have to make touch-based interface for same app, without keyboard and advanced touch events. All touch clicks are actually same as mouse clicks and I need to have 3 buttons/links that behave same as F5, F7 & F9 keys.
Don't ask for reasons, all I can say is that I need to keep that key bindings.
Can I assign mouse click on link to act like F-key is pressed?

In Jake's answer is most of solution and based on that I gave the whole answer, because is not so easy on first glance for beginners to modify functionality.
This is modified function from this thread:
function simulateKeyPress(target, options) {
var event = target.ownerDocument.createEvent('KeyEvents'),
options = options || {};
// Set your options or || default values
var opts = {
type: options.type || "keypress",
bubbles: options.bubbles || true,
cancelable: options.cancelable || true,
viewArg: options.viewArg || null,
ctrlKeyArg: options.ctrlKeyArg || false,
altKeyArg: options.altKeyArg || false,
shiftKeyArg: options.shiftKeyArg || false,
metaKeyArg: options.metaKeyArg || false,
keyCodeArg: options.keyCodeArg || 0,
charCodeArg: options.charCodeArg || 0
}
// Pass in the options
event.initKeyEvent(
opts.type,
opts.bubbles,
opts.cancelable,
opts.viewArg,
opts.ctrlKeyArg,
opts.altKeyArg,
opts.shiftKeyArg,
opts.metaKeyArg,
opts.keyCodeArg,
opts.charCodeArg
);
// Fire the event
target.dispatchEvent(event);
event.stopPropagation;
}
And now we call it on desired element/event for desired key to be pressed. Second argument is object with all options changeable (in my case keyCodeArg: 116 is only needed to be send to simulate F5 key press).
document.getElementById(element).addEventListener('click', function() {
simulateKeyPress(this, {keyCodeArg: 116});
});
Mozilla Developer Network has nice articles about KeyboardEvents and initKeyEvent.

There are two ways to do this I guess.
The simple way would be to have your F-keys call a function, and simply call the same function when catching a mouse event.
The other way would be to catch the mouse event, and fire a F-key press event. Then it would pretty much be a duplicate of this question:
How to simulate a mouse click using JavaScript?

Related

JS dispatchEvent not working

Usually i don't put this kind of so specific question in SO, but i'm struggling with this issue for days, so i'm seeking for some help here.
I'm building an app to automate a task in web version of Whatsapp (https://web.whatsapp.com/). My goal is to click on a button on the interface to show some options, and then click on the same button again to hide it.
To simulate what i want to do manually :
1 - Open Whatsapp Web.
2 - Click on the 'Attach' button on the upper right corner of the interface, as shown in the image below.
3 - The attach options will show, as the image below :
4 - Click on the 'Attach' button again, and the attach options will hide.
That's it, but i want do this programatically using Javascript (pure JS, no JQuery).
To achieve the task in step 2, i'm using the code below with success :
var nodes = document.getElementsByTagName('span');
if (typeof lastElementId == 'undefined')
var lastElementId = 0;
var result = undefined;
for (var i = 0; i < nodes.length; i++) {
var h = nodes[i].outerHTML;
var flag = false;
flag = (h.toLowerCase().indexOf('data-icon="clip') > -1);
if (flag) {
result = h;
lastElementId = i;
break;
}
}
if (result !== undefined) {
function triggerMouseEvent(node, eventType) {
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent(eventType, true, true);
node.dispatchEvent(clickEvent);
}
triggerMouseEvent(nodes[i], "mouseover");
triggerMouseEvent(nodes[i], "mousedown");
} else {
console.log('Not found');
}
;
The code above will work to do the step 2, but won't work to do step 4. Manually when i click in the Attach button after the options are show, the options will hide. But not using my JS code.
What am i missing here ?
Thanks in advance !
To fix the closing problem:
Right click on the attach element.
Select inspect element in chrome browser
In the right panel select Event Listeners tab and find mousedown section
Click the handler code and detect that we need to pass specific screenX and screenY to satisfy this particular business logic and pass through to n.uie.requestDismiss() part which apparently does what is says.
So now we have enough information to try a possible solution, which apparently works for now. Goes like this:
const toggleAttach = () => {
// select the span with reliable identification like data-*
const clipNode = document.querySelector('[data-icon="clip"]');
// take its element, i.e. the button itself
const clipButtonNode = clipNode.parentNode;
// extract the current offset position relative to the document
// more info here https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
// we can use this for filling in the non-0 screenX and screenY
const clipButtonNodeClientRect = clipButtonNode.getBoundingClientRect();
clipButtonNode.dispatchEvent(new MouseEvent("mousedown", {
bubbles: true,
cancelable: true,
screenX: clipButtonNodeClientRect.x,
screenY: clipButtonNodeClientRect.y
}));
}
Now to understanding why the first mousedown works for opening:
This is much harder to reverse engineer, but what I managed to find is if you install React DevTools (since whatsapp web is written in React) extension and open its tab in DevTools you will see:
And there you will find:
So we can make a very vague conclusion that opening and closing is handled in separate functions. Rest is up to you to figure out.
Hope this helped.

Disable ALT+F4, yes I know it isn't recommended

I need a JavaScript script that would disable users from closing using ALT+F4. I have looked everywhere but it just everyone just says it isn't advised.
May not even be possible, if it isn't I will just have to detect when the user does quit out this way and log it in a database.
Here is my current script, it detects if the user presses either ALT or F4, but I can't get it to cancel that key press. Is there a way to make the browser think the user pressed another key as well so the combo would be ALT + G + F4 for example, which would disrupt the ALT+F4 combo?
//Run on keydown, disable user from quiting via ALT+F4
document.onkeydown = function(evt) {
evt = evt || window.event;
//Get key unicode
var unicode = evt.keyCode ? evt.keyCode : evt.charCode;
//Check it it's ALT or F4 (115)
if (unicode == 115 || evt.altKey == 1)
{
window.event.cancelBubble = true;
window.event.returnValue = false;
}
};
That key event is (on most OSs I guess) processed by the OS before it'S even sent to the browser, so cancelling the event inside the browser won't help a thing - even if it was Javascript that is executed inside the browser's UI, not only the current document.
Therefore - what you're trying to do cannot be done.
One can prevent the resulting window closure with:
window.onbeforeunload = funcRef
I think readers landing here might want to be reminded of this (as I did).
For related details, see
Jquery prevent window closing
try to use the code below:
window.webContents.on("before-input-event",(event,input)=>{
if(input.code=='F4'&&input.alt)event.preventDefault();});

dojo aspect and key press

Is there a way to capture a key press event with dojo/aspect and aspect.after?
I am using a third party Javascript API (ESRI JS API v3.4) that provides a widget for drawing graphics on a map. The draw toolbar widget has an onDrawEnd event that provides the shape of the drawn graphic object as a parameter. I need to determine if the user was pressing the CTRL or SHIFT key while drawing on the map with this widget, but I use aspect.after(drawingToolbar, "onDrawEnd", myhandlerfunction, true) to connect the drawing event.
The only way I know how to determine if a key is pressed is by using an event object, which is not provided when using aspect like it is with dojo/on.
Any ideas how I can determine if a key is pressed here?
Maybe u musst go another way to catch up a Key-Event.
This is how i catch the "Enter"-Event in a Textbox. When the Enter-Key is hit, the function zoomToAnlage() is called. It's important that this event listener is already loaded in the ini-phase.
Sure, this is not a total resolve for your Question, but maybe it shows a way how you can handle it.
function initKielAnlagenNummernSuchen(){
queryTaskAnlagenNummern = new esri.tasks.QueryTask(restServicesLocation + NameSearchService + "/MapServer/23");
queryallAnlagenNummern = new esri.tasks.Query();
queryallAnlagenNummern.returnGeometry = true;
queryallAnlagenNummern.outFields = ["ANLAGE"];
require(["dojo/keys","dojo/dom","dojo/on"], function(keys, dom, on){
on(dom.byId("selectAnlagenNummer"), "keypress", function(evt){
var charOrCode = evt.charCode || evt.keyCode;
if (charOrCode == keys.ENTER) {
zoomToAnlage();
}
});
});
}
Here's a Link to dojo/keys : http://dojotoolkit.org/reference-guide/1.8/dojo/keys.html?highlight=keys#id2
Regards, Miriam
dojo.aspect can't connect to events, only functions. However you should be able to aspect to a function that is handling that event, and steal its args.
aspect.after(drawingToolbar, "someHandlerFunctionWithTheEventArg",
function(args){
// access the event from the args here
}, true);

Web page: detect and block certain keyboard shortcuts

I want to detect and block certain keyboard shortcuts on a web page. For example, say I want to prevent alt+tab for switching apps (just an example, assume any global shortcut).
Here's as far as I can think it out:
attach a keyboard event listener to
document (or window?)
use event.which to check which key
combination was pressed
if it was a blacklisted shortcut,
stop the browser from executing it
But, I don't know how to
A) detect multiple keys (e.g. alt and tab together), or
B) stop them from executing (can I just return false?).
Can anyone tell me how to accomplish the above?
You want to prevent screenshots from being taken? Forget it right now.
No matter what elaborate mechanisms you put into place, they will be trivial to circumvent by un-focusing the browser window (or just the document, e.g. by clicking into the address bar), and pressing the screenshot key then.
There is no chance for you to do this except by installing client software on the computer that controls what the user does, or maybe using some proprietary ActiveX control that makes its contents un-print-screenable. Both approaches are hugely difficult and have tons of downsides.
You cannot block keyboard combinations that belong to the OS. Only keyboard combinations that roam inside the browser and are not OS specific.
If you want to protect your content, don't publish it in public. Or put a decent license on it
// lookup table for keycodes
var key = { s: 83 };
document.onkeydown = function (e) {
// normalize event
e = e || window.event;
// detecting multiple keys, e.g: Ctrl + S
if (e.ctrlKey && !e.altKey && e.keyCode === key.s) {
// prevent default action
if (e.preventDefault) {
e.preventDefault();
}
// IE
e.returnValue = false;
}
};
Detecting Keystrokes Compatibility Table (QuirksMode)

Detect Close window event in Firefox

I know it is a very asked question, but believe me I don't find the answer through the Web.
My purpose is to trigger the message box only if the user clicks on the close (X) button.
The user continues to get the message box if he clicks on the back/forward button and also if he uses F5, CTRL+R, ...
I do not want to associate any other action than the window close button click as behind, there will be a session kill with Ajax. So it is not acceptable to kill the session if the user types F5 button.
Here is my code. For info, I know that there is a way in IE to check the event object clientY, but this does not work in Firefox.
$("a").click(function () {
window.onbeforeunload = null;
});
window.onbeforeunload = function (e) {
var closewindowmessage="If you leave this page, your session will be definitely closed.";
e = e || window.event;
// For IE and Firefox
if (e) {
e.returnValue = closewindowmessage;
}
// For Safari
return closewindowmessage;
};
There's no definitive way of detecting why/how a page is being unloaded. You could rebuild your site to use the now ever so popular "anchor navigation" method which stores data in the HTML anchor, such as http://www.example.com/page#something=something. This would at least typically solve the problem for the back/forward buttons but not when the user is reloading the page.
Other than that, you could employ various ad hoc ways of tracking the mouse and keyboard action before the user tries to unload the page. You could for example track when the user drags the mouse diagonally up to the right – that probably means he's just about to close the the window/tab, so keep the message. Diagonally up to the left – that probably means he's just about to click the back forward buttons or maybe enter something to the address field. If you're really serious, conduct a study of how people move the cursor and correlate that with whether they're about to close the page or do something "allowed". Then again, on a Mac the close button is in the upper left corner of the window. And so on and so forth. It'll still just be best guesses.
You could also track upward mouse movements and show a big red message in the browser viewport (not a popup/alert) to warn the user before he even considers leaving the page.
Tracking keyboard events is a little bit more deterministic, but still requires some cross browser and platform research. I leave you with this code, which I'm hoping may work as a boilerplate. It logs the key presses and suppresses the message if F5 or Apple+R (Mac) was pressed. Otherwise it will show a message containing a list of all logged key presses.
The analysis needs testing and extension; it's only been tested on Firefox Mac. One bug that I can immediately point out is that if you press Apple+R,R you'll still get prompted because the second page instance never recorded any keydown event for the Apple key – only for the R key. It will also fail if the user presses something inbetween, like Apple+L,R. You might be fine with just checking if the last key pressed was R.
<script>
// Create an empty array.
window.keys = [];
// Log every key press
window.onkeydown = function (e) {
var evt = window.event || e;
var keyCode = e.keyCode || e.which;
window.keys.push(keyCode)
}
function analyzeKeyPresses(){
keys.reverse(); // Reverse the array so it's easier to handle.
var doBlock = true;
// Here we only apply certain checks if there are enough keys in the array. Don't want a JS error...
switch(window.keys.length){
case 0:
doBlock = true; // Redundant. If there are no key presses logged, assume we should prompt the user.
break;
default: // Two or more key presses logged.
if(keys[0] == 82 && keys[1] == 224) doBlock = false; // User pressed apple+r on a Mac - don't prompt!
if(keys[0] == 82 && keys[1] == 17) doBlock = false; // User pressed ctrl+r on Windovs (untested) - don't prompt!
// Note: No break! Intentional fall-through! We still want to check for F5!
case 1: // One or more key presses logged.
if(keys[0] == 116) doBlock = false; // User pressed F5 - don't prompt!
}
keys.reverse(); // Un-reverse the array in case we need to use it again. (Easier to read...)
return doBlock;
}
window.onbeforeunload = function (e) {
var closewindowmessage=window.keys.join(" ");
var blockUnload = analyzeKeyPresses();
if(blockUnload){
e = e || window.event;
// For IE and Firefox
if (e) {
e.returnValue = closewindowmessage;
}
// For Safari
return closewindowmessage;
}
};
</script>
1 2

Categories

Resources