Finding out which keyboard generated a key event in javascript - javascript

Is there some way to determine which keyboard connected to a device sent a particular key event in JS? For example, a laptop with a USB keyboard will happily honour keypresses on both keyboards but I cannot seem to find a way for the browser to tell me which source a key event came from so I can filter based on that (e.g. for player 1/2 input filtering for a browser based game, keyboard vs. "virtual instrument" for a browser based composing tool, etc.)
I couldn't find anything in the key events specs on MDN that suggests this is possible, but I'll be more than happy to take on any creative hack that makes this work "despite" rather than "thanks to" the spec.
Someone did ask this question back in 2013, and while its answer suggests using the gamepad API as workaround, it's now 2018 and three years of changes to JS APIs means that this question is worth reasking, in order get an answer based on the current state of the browser.

I dont know if it is already possible, but if would try something like that, i would study the WebUSB Api:
https://developers.google.com/web/updates/2016/03/access-usb-devices-on-the-web
https://wicg.github.io/webusb/
Not so easy, but seems possible

It's not possible at present.
WebUSB won't allow access to HID devices, and WebHID won't allow access to devices (including keyboards) that are already supported by high-level APIs.
I've started a topic at the WICG incubator: https://discourse.wicg.io/t/identify-which-of-multiple-keyboards-an-event-came-from/3416

Related

Beginner - Why is execCommand() obsolete?

Not a coding question, and the question applies to a wider tag of XYZ becoming obsolete, but asking as there seems to be tons of comments on the web about how there are so many apps out there that use this command.
Why is this now obsolete? (tried executing on vscode, would not work)
Based on the MDN entry for Document.execCommand, in most cases the APIs made available by execCommand can be achieved using other modern, purpose-built JavaScript APIs that behave the same way across browsers.
Each command in execCommand's toolbox was contentiously implemented in different ways across browsers meaning that testing on every single browser was a necessity of web development. Just skimming through the draft spec you linked in the comments shows all of the notes detailing some of the different ways they were implemented. Because of these differences there was a shift away from HTML-based rich-text document rendering to canvas-based rendering for Google Docs and img-based rendering for Office 365 Web Apps (at least for viewing them, editing is still HTML-based).
Additionally, the MDN entry notes:
Return value
A boolean value that is false if the command is unsupported or disabled.
Note: document.execCommand() only returns true if it is invoked as part of a user interaction. You can't use it to verify browser support before calling a command. From Firefox 82, nested document.execCommand() calls will always return false.
Because execCommand can only be invoked as part of user interaction, it might work in one bit of your code, and not in another - which can cause time-consuming headaches that involve learning the intricacies of JavaScript's event loop.
Importantly, with the advent of JavaScript running on mobile devices and modern JavaScript frameworks having their own "event->queue->render" loops, what even defines a user interaction event? A click, tap, keypress, etc? What about a screen rotation or resizing the window? What about asynchronous event changes where you make a server request and then show the user something based on the result? How would the engine know those two things are linked together with modern Promise-based APIs rather than callback-based APIs?
If you want to do some further digging, take a look at this thread on another question asking about what replacements are available to execCommand().

Can I open the OS native emoji picker in a web page?

I know there are lots of javascript plugins and libraries to allow users to pick emojis for text inputs, but windows and mac already have native emoji pickers (⊞ Win. or CTRL⌘Space), Is there a way for me to open these native emoji pickers when a user clicks in a text field instead of installing plugins in my website?
I already tried emulate button key press, but it didn't work at all.
Short answer is no.
In order to access any OS feature from javascript, you need a corresponding browser API to support.
AFAIK, there isn't an API for that. There's a discussion here which suggests adding <input emoji /> to standard but seems no traction gained.
Edit: Below is my original answer, revised. Comments pointed out I was focusing on the wrong aspect of the question, I totally agree.
However, the OP obviously has some wrong idea about what you can do in javascript to leverage browser ability. So I think it's still worth clarification.
You can't send arbitrary emulated keyboard event from js and hoping the OS will respond. Were it possible, it'd be a severe security issue on browser's part. Imagine open a website and it fires a series of keyboard event to your OS and wipes out your desktop (totally feasible through shortcuts).
You need to understand the runtime env inside the browser is basically isolated from the one of native OS. Whatever OS feature that's accessible to your javascript is totally up for browser vendors to decide. For security reason, they are super careful in making these decisions.
Also, make a distinction on "what browser can do", and "what browser allows you to do in js". Seeing Chrome has an "Emoji & Symbols" context menu item, doesn't necessarily mean it decides to grant you the same ability in js.
To further clarify why the emulated keyboard event is fundamentally different from the native one, I include a graph here. The blue arrow is how emulated keyboard event flows. The farthest place it can reach is the browser's internal event bus. It never got a chance to reach the OS event bus, so no way to notify native emoji picker.

Gamepad API "gamepadconnected" not working

I am using the Gamepad API "gamepadconnected" function which is not working properly. However, the "gamepaddisconnected" function works for some reason. Upon connecting my bluetooth controller, nothing shows in the console, however, it does show the information displayed when disconnected.
What I have here is very basic and standard:
window.addEventListener("gamepadconnected", function(e) {
console.log("Controller connected");
});
window.addEventListener("gamepaddisconnected", function(e) {
console.log("Controller disconnected");
});
What am I missing here? Where did go wrong? I made sure the first focused page is the one with the scripts above. Thanks for your help.
MDN states that "If a gamepad is already connected when the page loaded, the gamepadconnected event is dispatched to the focused page when the user presses a button or moves an axis.". So your page will not always receive the gamepadconnected event when you connect the pad. https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API/Using_the_Gamepad_API
So it's best to e.g. let the user press a button to get your application started. This is also useful when there are multiple gamepads connected to the computer and your application has to know which one to use.
Chrome is notorious (certainly to me after working with it!) for its, shall we say, individual implementation of the GamePad API. One issue being that as far as I'm aware, it doesn't yet support the "gamepadconnected" event robustly, and you have to poll the gamePadConnected property of the GamePad object in order to do anything sensible with connections and disconnections. A total pain I know, but this is probably a reflection of the fact that the W3C standard for this API is still in flux. You'll also find that there are other issues, such as browser X on Windows behaving differently to browser X on Linux.
I don't know if anyone's tried plugging these devices into an Android or iOS device (probably superfluous to requirements on something with a touch screen unless you're planning to port a flight sim thereto!), but I suspect even more compatibility issues will arise if these experiments are performed. If you have the ability to dive into an Android smartphone with a USB port, and tinker with JavaScript in the smartphone browser, you may find even more hilarious issues coming to light.
As for legacy joysticks (such as my 10 year old Microsoft Sidewinder Pro USB), those have their own hilarity to throw at you. I'm currently struggling to make otherwise reasonable code work with the weirdness thereof, such as an axis property in the GamePad object being assigned to, wait for it, the hat switch, which on this device is a digital data source, not an analogue one. Be aware of a tidal wave of compatibility woes heading your way as you persevere with the GamePad API, until the W3C finalises the standard.

Is there a correct/recommended way of detecting my UWP app I'm running on a Phone?

Trying out Windows Universal apps with JavaScript I noticed the WinJS.Utilities.isPhone property is no longer available, which makes sense since there would be no reason to ask for that at runtime.
I do want to know just for testing purposes if there is a proper way of detecting the device my app is running in.
EDIT: My question is NOT about detecting a mobile browser. I'm talking about about a brand new Universal Windows App for Window 10 that can run on phones, desktops, tablets, Xbox, HoloLEns, IoT devices et all. WinJS had a property that would tell me whether I was running on the phone or not. That property is now gone. Please don't close this question due to duplicate with "detecting mobile browser". That is NOT what I need.
Caveat: Any form of device detection is fragile due to the dynamic nature of hardware - a new device could come along tomorrow that breaks your app's logic. It is best to use these APIs only for telemetry / analytics rather than to trigger runtime behaviour.
More often than not, what you really want to know is some attribute of the device or the app that is not inherently tied to the device family (does this device support SystemTray API? Is there a keyboard attached? Is the window more than 500px wide? etc.).
That said, in Windows 10 you can query the DeviceFamily via AnalyticsInfo.VersionInfo.DeviceFamily and it will tell you things like "Mobile" or "Desktop" or "Xbox" etc. (where "Mobile" could be any class of device - phone, tablet, etc.). There is also a property DeviceForm that might be helpful, but again you can't really rely on it at runtime to deterministically say you're running on "a phone."
So basically the answer is "you can use these APIs for telemetry but don't hard-code any values into your app lest it break when a new device arrives on the market." At the very least, always make sure you handle the case where the returned value isn't one you know about a-priori.
You can also check out the following links
http://www.abeautifulsite.net/detecting-mobile-devices-with-javascript/
http://www.sitepoint.com/detect-mobile-devices-jquery/
and of course a similar post here on stackoverflow with a good answer
Detecting a mobile browser
And talking about Windows 10, extracting from Winjs Github repo, here is the answer.
https://github.com/winjs/winjs/issues/601#issuecomment-87137485
There are numerous JS libs to detect which platform/device is used.
I personally love using this lib: https://github.com/kaimallea/isMobile
You will then be able to detect mobile device in such a way:
isMobile.apple.tablet
isMobile.android.phone
and so on.
In case you have an idea to implement such lib yourself, keep in mind that it takes some efforts to keep it up-to-date, because ways of detecting mobile device may change over time.
In general, common way of detecting user device is checking query headers.
Keep in mind, though, that you can't absolutely rely on this information - headers may be easily modified. Google for User Agent for more info.
So "omitting auth process for users with phones" is extremely bad idea

HTML5 Audio Output Patching

I was wondering if there is a way to control audio output device patching in HTML5/JavaScript? Like, if the user wanted to have one sound in my web app to go out of one audio device, and another sound out of a different audio device. I know the user can set the default output device on their computer, but for the web app I'm working on, I would like them to be able to send individual sounds to individual outputs while other sounds are playing, similar to the interface below (from a program called QLab).
I feel like the obvious answer is NO, and I do not want to resort to using flash or java. I MIGHT be okay with having to write some sort of browser plugin that interfaces with javascript.
So, after receiving basically zero helpful answers - and finding no further helpful information online, I think I figured out something that we, as developers, NEED to start requesting from browser vendors and w3c. We need to be able to request hardware access from users, in a similar fashion that we can request to access a user's location, or how we can request to send a user push notifications.
Until web developers are allowed the same control as native application developers over hardware, we will be left at a huge disadvantage over what we can offer our users. I don't want to have my users install third/fourth party plugins to enable a little more control/access to their I/O. Users should not have to be inundated with keeping more software than just their web browser updated to have websites run well and securely. And I, for one, do not feel like it should be necessary to write in more languages than HTML, JavaScript, CSS, and PHP to get the same experience a user would get from a native application.
I have no idea how we approach browser vendors about this, but I feel like it would be good to start doing this.
I know this is a little old, but just this year a method was added called "setSinkId" that you can apply to a media element (video, audio) to set the device that audio will be outputted to.
$('#video-element').setSinkId('default');
https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId
Though currently it seems only Chrome supports it. I haven't tested on Firefox or other web browsers.
I suggest you take a look at the Web Audio API:
Specs --- Tutorial
There is the destination property in the Web audio API. However it is a readonly property ... so not settable.
Here:
The destination property always correlates to the default hardware output of sound, whether it’s through speakers, attached headphones, or a Bluetooth headset.
I'm working on a sound installation based off web audio and have run into the same problem. I want to map different channel outputs to different speakers. have you had any progress on this?
This gentleman seems to have managed to do it: http://www.brucewiggins.co.uk/?p=311
I tested this out on a apogee quartet and it worked - outputting to 8 different channels.
I also found this article useful: http://www.html5audio.org/2013/03/surround-audio-comes-to-the-web.html
if (context.destination.maxChannelCount >= 4) {
context.destination.channelCount = 4;
}
// otherwise, let's down-mix to 2.0
else {
context.destination.channelCount = 2;
}
context.destination.channelCountMode = "explicit";
context.destination.channelInterpretation = "discrete";
context.destination.numberOfOutputs = 4;
While you can certainly use the splitter and merger nodes to assign to specific channels on the output, the actual devices you output are abstracted by the browser and inaccessible by your code.
I have done some experiments with 8-channel virtual audio cables and relaying that data to other sound devices outside of the browser. Unfortunately, I can't find a browser that will actually open an 8-channel sound card with more than 2 channels.
Hopefully, browsers in the future will provide more options. This flexibility will never come directly to JavaScript... and nor should it. This is an abstraction done for you, and if the browser uses it correctly, it won't be an issue.

Categories

Resources