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.
Related
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.
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
Is there any way to consistently detect PhantomJS/CasperJS? I've been dealing with a spat of malicious spambots built with it and have been able to mostly block them based on certain behaviours, but I'm curious if there's a rock-solid way to know if CasperJS is in use, as dealing with constant adaptations gets slightly annoying.
I don't believe in using Captchas. They are a negative user experience and ReCaptcha has never worked to block spam on my MediaWiki installations. As our site has no user registrations (anonymous discussion board), we'd need to have a Captcha entry for every post. We get several thousand legitimate posts a day and a Captcha would see that number divebomb.
I very much share your take on CAPTCHA. I'll list what I have been able to detect so far, for my own detection script, with similar goals. It's only partial, as they are many more headless browsers.
Fairly safe to use exposed window properties to detect/assume those particular headless browser:
window._phantom (or window.callPhantom) //phantomjs
window.__phantomas //PhantomJS-based web perf metrics + monitoring tool
window.Buffer //nodejs
window.emit //couchjs
window.spawn //rhino
The above is gathered from jslint doc and testing with phantom js.
Browser automation drivers (used by BrowserStack or other web capture services for snapshot):
window.webdriver //selenium
window.domAutomation (or window.domAutomationController) //chromium based automation driver
The properties are not always exposed and I am looking into other more robust ways to detect such bots, which I'll probably release as full blown script when done. But that mainly answers your question.
Here is another fairly sound method to detect JS capable headless browsers more broadly:
if (window.outerWidth === 0 && window.outerHeight === 0){ //headless browser }
This should work well because the properties are 0 by default even if a virtual viewport size is set by headless browsers, and by default it can't report a size of a browser window that doesn't exist. In particular, Phantom JS doesn't support outerWith or outerHeight.
ADDENDUM: There is however a Chrome/Blink bug with outer/innerDimensions. Chromium does not report those dimensions when a page loads in a hidden tab, such as when restored from previous session. Safari doesn't seem to have that issue..
Update: Turns out iOS Safari 8+ has a bug with outerWidth & outerHeight at 0, and a Sailfish webview can too. So while it's a signal, it can't be used alone without being mindful of these bugs. Hence, warning: Please don't use this raw snippet unless you really know what you are doing.
PS: If you know of other headless browser properties not listed here, please share in comments.
There is no rock-solid way: PhantomJS, and Selenium, are just software being used to control browser software, instead of a user controlling it.
With PhantomJS 1.x, in particular, I believe there is some JavaScript you can use to crash the browser that exploits a bug in the version of WebKit being used (it is equivalent to Chrome 13, so very few genuine users should be affected). (I remember this being mentioned on the Phantom mailing list a few months back, but I don't know if the exact JS to use was described.) More generally you could use a combination of user-agent matching up with feature detection. E.g. if a browser claims to be "Chrome 23" but does not have a feature that Chrome 23 has (and that Chrome 13 did not have), then get suspicious.
As a user, I hate CAPTCHAs too. But they are quite effective in that they increase the cost for the spammer: he has to write more software or hire humans to read them. (That is why I think easy CAPTCHAs are good enough: the ones that annoy users are those where you have no idea what it says and have to keep pressing reload to get something you recognize.)
One approach (which I believe Google uses) is to show the CAPTCHA conditionally. E.g. users who are logged-in never get shown it. Users who have already done one post this session are not shown it again. Users from IP addresses in a whitelist (which could be built from previous legitimate posts) are not shown them. Or conversely just show them to users from a blacklist of IP ranges.
I know none of those approaches are perfect, sorry.
You could detect phantom on the client-side by checking window.callPhantom property. The minimal script is on the client side is:
var isPhantom = !!window.callPhantom;
Here is a gist with proof of concept that this works.
A spammer could try to delete this property with page.evaluate and then it depends on who is faster. After you tried the detection you do a reload with the post form and a CAPTCHA or not depending on your detection result.
The problem is that you incur a redirect that might annoy your users. This will be necessary with every detection technique on the client. Which can be subverted and changed with onResourceRequested.
Generally, I don't think that this is possible, because you can only detect on the client and send the result to the server. Adding the CAPTCHA combined with the detection step with only one page load does not really add anything as it could be removed just as easily with phantomjs/casperjs. Defense based on user agent also doesn't make sense since it can be easily changed in phantomjs/casperjs.
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.
I'm experimenting with HTML5 geolocation, and embedded a small test script into a page to return my present co-ordinates.
The current application I have in mind for using this is as a 'nice to have' feature on site i'm working on - it includes a 'find my nearest' lookup on some locations, and I figured that if you had a location aware device, I could easily include 'to my current location' alongside the normal 'to my postal/zip code'. I'm not interested in loading a bunch of extra libraries and fallbacks for such a small and non-essential feature. If you have a capable device, great, if not, you won't ever see the option.
So I tried the script on an iPad, and as expected - I was prompted for permission to use my present location, to which I agreed, and my test script returned my present location. Total win.
I tried the same on my desktop, since i'm using Firefox 4 and its a HTML5 compliant browser. It asked me if I wanted to share my location, and then promptly returned the error that it didn't know my location (because its a desktop computer and has no GPS). I thought this rendered the original question of 'do you want to share your location' somewhat pointless - it could needlessly annoy people who might have thought they could use a feature that they in fact can't.
So, what is a reliable technique to detect if:
a) The browser can access HTML5 geolocation
AND
b) The browser knows or can find out what the users location is.
Without actually calling the geolocation function beforehand, and asking the user an annoying, and unnecessary question?
For a) i'm simply using:
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showCoords,handleGeoErrors);
}
But for b) the only answer I have involves having called getCurrentPosition, which triggers the question to the user.
Any thoughts on this, anyone?
There's not going to be a way to do this because the way a browser finds out whether or not it can get geolocation information (in the absence of a direct connection to a GPS device) is to send a request to the configured geolocation service and see what it says. Unfortunately at that point it's already shared the personal information that the annoying question is supposed to prevent being shared without permission.