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.
Related
Context
A game shipped as a progressive web app which has timers (setTimeout, setInterval) and websocket connections to get real-time communication.
What is happening
Everything is fine as long as the user stays in the app. But when the user goes to another tab, or another app or turns off the screen (in case of mobile), it becomes a "hellish unknown world".
Websockets may or may not become "paused" or "turned off"
Timers look like they are being throttled or debounced.
This behaviour seems to depend on browsers and platform and, maybe, even depend on the particular user behaviour. I guess browsers and OS have their own lifecycle / mechanisms to save battery and/or computation.
When the user comes back, the app is in an unknown state and I am struggling to restore the state properly.
Regarding websockets I have auto-reconnection with socket.io and reconnecting-websocket but it's not enough to solve everything.
Looking for answers
What are the "lifecycles" of the different browsers regarding these? Is this documented? When do they decide to turn off and throttle?
What do they do exactly to websockets? Browsers just disconnect them?
What do they do exactly to timers? They throttle them or debounce them or something else?
What happens to javascript execution in general? Paused / destroyed / throttled?
Is there a way to hook into some kind of browser lifecycle event when it's going to turn things off? The only thing I could find might be the visibility API
Is there a way to artificially reproduce this behaviour to be able to test solutions? It's especially hard on desktop. Websockets can't be turned off and chromium developers don't seem in a hurry to help an issue from 2014(!): websockets not included when using connection throttling
Regardless of the above, is there a pragmatic cross-browser solution to detect / solve this problem? (for example from experience, Firefox on desktop seems to behave completely different compared to Chrome, and an iPhone will disconnect far more often than an Android)
Related Links
Safari dropping web socket connection due to inactivity when page not in focus
Not exactly sure, but you could use service workers. As much as I know, they run in background even if your tab is not opened and get terminated if your tab closes.
Btw. lifecycles of browser tabs seem to be different on every browser, since every browser handles it different. From what I see the browser can freeze tabs if it needs more memory for other things.
Here is the docs from Chrome.
I remembered that there are some events, like onload that tell you if a user has left or reopened the tab. You could use these event to reconnect etc..
I would give different advice regarding how to design your app. From what I understand your intention is to add more logic in order to understand if the user is no longer active in the browser. This entails a different problem which is browser specifics to implement that logic. With that in mind, I would instead invest in have better error handling, both in the server and client.
Errors won't be browser-specific. Handling those will make your app more resilient and agnostic to browser changes, that could eventually change, let's say, the way they hibernate a tab, any other feature that a vendor might implement in the future.
This is an idea that you can find in services architecture, but the same pattern applies to any web-app. You might want to look for Design-for-Fail concepts:
Complexity makes it infeasible to assume robustness on the part of the systems upon which one relies. Instead, one needs to design systems and applications at any given layer in the IT stack-based to assume the possibility of failure at lower levels. Design-for-fail necessitates thinking about fault tolerance at all layers. No longer can application developers confine themselves to thinking about functionality.
https://www.oreilly.com/library/view/designing-delivery/9781491903742/ch04.html
I am developing for Resco Mobile CRM and I am writing custom JavaScript libraries for the application, which calculate some fields for an Order and an Order Product.
Now I am experiencing a bug where I can't retrieve the ID of an Order from the Order Product (it has a lookup to the Order), but it happens in extremely rare cases. So far I've rewriten the code to retrieve it either from the lookup field or retrive it from a script on the Order where I save the ID in a localStorage variable. I've added a lot of logs as well (that's how I found that the ID is null).
These are the cases when the bug appeared:
After a synchronization between the Resco CRM and our CRM implementation (it usually disappears after another synchronization).
At the demo day, it appeared constantly and synchronizing the device again didn't helped (but the customer has very week network).
So far I've been debugging it for days and can't replicate it. I believe it is a 'networking issue' (some date is missing when the synchronization occurs), or a crash of the application (I recently found a similar crash on Resco CRM and Resco admited it was an error on their application, but they dismissed this one).
What can you suggest me to do in this case?
Thanks.
Best regards,
Evgeni Dyulgerov
Maybe it's not the answer, but it might help you to debug it.
On Chrome DevTools, you can emulate mobile devices, an inside that option you can simulate the bandwidth as you where in a terrible network.
I've never worked before with that CMS, but it seems that you're right about timing on the info retrieval. Maybe you should think about working with promises, and until the info is not fulfilled don't do a thing.
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
I've found users are not getting updates to my Chrome App because they keep the app open, and let their browser get out of date (i.e. the hamburger icon is red for a prolonged period).
Empirically it seems the chrome.runtime.onUpdateAvailable event is not triggered when the browser itself is out of date.
At a minimum I'd like to display an in-App warning UI to tell the user the need to restart the browser to get updates (and eventually, block usage of the app altogether until updated). It seems like chrome.runtime.onBrowserUpdateAvailable was intended exactly for this, however that event is marked as long deprecated, but the replacement isn't good for this use case: chrome.runtime.onRestartRequired is only supported on Chrome OS, for kiosk apps.
The relevant bugs, http://crbug.com/177029 and http://crbug.com/242983 didn't really explain if onBrowserUpdateAvailable ever worked on non-ChromeOS versions, and if so, why it made sense to deprecate it without replacement on those other OSes.
Am I going about this all wrong? should I just use the deprecated event? Do people know that event works reliably for this scenario across OSes?
(I haven't experimented with the APIs in great depth, and only have the documentation to go on, as browser updates are sufficiently infrequent it's going to be a very long experiment to run, and API behavior may change across versions during that experiment anyway).
If you need users to update to your latest client in order to work with your non-backward-compatible server, then you have complete control over the situation: detect the client mismatch and cease functioning (with a message explaining why) until the user restarts Chrome and gets your updated app.*
But if you're merely annoyed as a matter of hygienics that users aren't updating, it's hard to justify such a drastic approach. Moreover, by definition you're dealing with users who for some reason just plain don't care about updating anything, which is why they've been ignoring the red hamburger for who-knows how long. If this is the case, then adding yet another noisy notification probably isn't going to cure their behavior. Cue your personal equivalent of Serenity Prayer here.
*Side note: I'm surprised that app updates would be stalled because of lack of browser updates. Are you sure your app wasn't updated to specify a minimum_chrome_version? That case would be understandable, because we wouldn't want to update a Chrome App to a version known to be incompatible with the current browser.
I'm developing a map based web application and I would like to offer users the ability to "Use current location"
I can easily check for the availability of the geolocation api as follows:
if (navigator && navigator.geolocation) {}
And once I've actually called navigator.geoLocation.getCurrentPosition I can easily check the accuracy of the result, or if the result is available at all.
However, I would like to only display the "Use current location" button when there is a good chance that it might work well, i.e. produce a result accurate to within a couple of hundred meters. I'd like to make this decision without asking the user to share their location.
My best guess so far is to basically attempt to always hide this button on a desktop or laptop PC, probably by using Modernizr touchscreen detection. This clearly won't be 100% effective due to touchscreen laptops, but maybe it's better than nothing.
I'd also like to avoid doing anything too elaborate on the server side. This is the only functionality in my app so far that requires device detection of any sort, so WURFL or similar user agent look ups are out of the question. I'd like to do it all client side without too much bloat
Thanks for any help
Unfortunately, no. Getting the geolocation accuracy of a user is private information so you need to make the request to the end-user first (as in navigator.geolocation.getCurrentPosition). The accuracy of the gps is device specific information, so the ONLY way you could get it would be on the client and not on your server.
Sorry there isn't a better solution for you. If you're making a mobile app, you could always use phonegap/cordova and use or create a plugin that could get you this information.