I have the following JavaScript code that utilises browser detection and navigator.platform property and the navigator.userAgent property of the navigator object. This is used to execute environment/platform specific code based on what device an end user is browsing on.
The issue stemmed from the behaviour of Bootstrap tooltips on Android and iOS devices - the tooltips appears when the user hovers over an <a> element, now touch devices have no concept of hover and do not handle it well (for example on iOS using Safari the tooltips are not able to be dismissed after the first touch, on Android using Chrome the tooltip is visible for a split second). The decision was made that tooltip functionality should not be available to users on mobile devices, as they are not handled well.
The issue is visible here on the <a> elements (a tooltip is intentionally applied to the iOS and Android code blocks to demo issue) used as links with an icon that read 'Disco', 'Bouncy Castles', 'Clowns' etc. (if viewed on a phsyical iOS or Android tablet above 768px): http://fun-booths.co.uk/dev/
HTML (one fragment)
<span class="dec-block hidden-xs">
<span class="promo-details">
<i class ="fa fa-headphones"> </i>
<span class="promo-a-cont">
<a href="http://www.bestdiscointown.co.uk" title="" class="customtooltip" data-original-title="Best Disco in Town offer a professional DJ suitable for any party.">
<span class="dashed"> Disco </span>
</a>
</span>
</span>
JS
As you can see the code says if isOS tests true then don't execute the tooltip JavaScript, the else if statement then checks if isAndroid tests true and again no tooltip JavaScript is executed. Finally an else statement says if the users is on any other system then execute the tooltip JavaScript.
$(document).ready(function(){
var isOS = /iPad|iPhone|iPod/.test(navigator.platform);
var isAndroid = /(android)/i.test(navigator.userAgent);
///////////////////////////////////////// if OS
if (isOS){
///////////////////////////////////////// if Android
} else if(isAndroid){
///////////////////////////////////////// if another system
} else {
toolOptions = {
animation: true,
placement:"top",
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
container:"body"
};
$('.customtooltip').tooltip(toolOptions);
}//end if system
});
I need to increase my understanding of this issue and potential solutions, so please if you can answer my questions.
Is the navigator object a native JavaScript object like the date object is?
If the navigator object is native, then am I correct in saying this is surely built in to all modern web browsers as they have a JavaScript engine? So why is this considered a bad practice?
After performing research on MDN - the navigator.platform property and the navigator.userAgent are stated as:
'This feature has been removed from the Web standards. Though some
browsers may still support it, it is in the process of being dropped.
Do not use it in old or new projects. Pages or Web apps using it may
break at any time.'
and:
Browser identification based on detecting the user agent string is
unreliable and is not recommended, as the user agent string is user
configurable.
Given that this approach of browser detection does not abide by web standards how can I prevent tooltips being displayed to the user on touch devices?
I have tested this on multiple versions of real Android tablets and iOS tablets and this JavaScript fix does work - even though it is bad practice. The popovers do not appear and therefore I consider the issue to be fixed. However are there other touch device scenarios I haven't considered outside of Android and iOS devices.
Related
I have seen very many questions asking how to detect if a device is mobile or not. Generally, they fall into 3 categories:
Check the screen size/viewport
Check the User Agent
Use a library, such as Modernizr to work around browser capabilities.
After implementing what I could, I still run across a situation which I have never seen asked or addressed; On many mobile browsers, there is a "Request desktop site" (Chrome) "Desktop Mode" (Dolphin) or "Desktop View" (HTC Sense).
I have chosen strategy #1 above, which works unless the page is viewed in desktop mode. Implementing #2 has drawbacks (spoofing, uncatalogued agents, etc.).
Is there a reliable (cross browser) way to detect Desktop Mode on a mobile browser with Javascript? jQuery or other libraries would be okay, but it should be based upon feature detection, rather than an array of User Agents.
So, Finally I have proven method to detect this. There's little tricky but got Exact Solution.
STEP 1
Install device-uuid Library , ( Here already mentioned. How to install )
<script src="https://raw.githubusercontent.com/biggora/device-uuid/master/lib/device-uuid.min.js"></script>
<script>
var user_configuration = new DeviceUUID().get();
console.log(user_configuration);
</script>
// output
// {"isAuthoritative":true,"isMobile":true,......"resolution":[980,1104],"browser":"Chrome"}
STEP 2
Detect device width
var curr_width = parseInt((window.innerWidth).toFixed());
STEP 3
Now need to compare curr_width with user_configuration.resolution[0] (width)
If both are same then this is normal view and if not then it's "DESKTOP VIEW" . attaching screenshot.
if(curr_width == user_configuration.resolution[0]){
alert("normal_view");
}else{
alert("desktop_view");
}
Screenshot of Desktop Mode ON in mobile browser
Screenshot of Normal mobile view
There is no way for a webpage to detect whether the device is actually a desktop computer or not. When "Request desktop site" is enabled, the phone acts just like a desktop does. One way to check this is to check the OS of the device. However, some phones use windows as their OS, so this won't work on windows phones.
Can I use Javascript in a cross-platform way to get the compass heading in iOS and Android (with Chrome), without using something like PhoneGap? I know iOS has DeviceOrientationEvent, but I can't find any equivalent on Chrome for Android.
As a primer you should review this previous related StackOverflow answer and be familiar with the general practical considerations for using DeviceOrientation Events in web applications.
The simple solution I provided in my previous related StackOverflow answer only applies to browsers that implement absolute deviceorientation events (i.e. browsers where the deviceorientation alpha property is compass-oriented). That means the solution provided there currently only works in Android browsers and not iOS-based browsers or any other browser that does not provide absolute-based deviceorientation event data.
To reliably obtain the current compass heading across both Android and iOS browsers today you need to handle both absolute and non-absolute implementations that provide the additional webkitCompassHeading property and make sure to account for any current screen orientation changes as part of that. AFAIK the only library that currently does this is Full Tilt JS (disclaimer: I am the author of this library).
The following code will give you the same correct compass heading across both iOS and Android browsers, taking account of the differences in device orientation implementations and applying any necessary runtime screen orientation transforms too:
<!-- Include the Full Tilt JS library from https://github.com/richtr/Full-Tilt-JS -->
<script src="fulltilt-min.js"></script>
<script>
// Obtain a new *world-oriented* Full Tilt JS DeviceOrientation Promise
var promise = FULLTILT.getDeviceOrientation({ 'type': 'world' });
// Wait for Promise result
promise.then(function(deviceOrientation) { // Device Orientation Events are supported
// Register a callback to run every time a new
// deviceorientation event is fired by the browser.
deviceOrientation.listen(function() {
// Get the current *screen-adjusted* device orientation angles
var currentOrientation = deviceOrientation.getScreenAdjustedEuler();
// Calculate the current compass heading that the user is 'looking at' (in degrees)
var compassHeading = 360 - currentOrientation.alpha;
// Do something with `compassHeading` here...
});
}).catch(function(errorMessage) { // Device Orientation Events are not supported
console.log(errorMessage);
// Implement some fallback controls here...
});
</script>
Here is a demo that demonstrates this technique to obtain the compass heading the user is facing. It should work well on both iOS and Android browsers.
The implementation of the code in that demo is as shown above and can be viewed on Github at ./scripts/compass.js:L268-L272.
Yes you can! Unfortunately the alpha doesn't work on iPhones/iPads. With Mobile Safari, alpha is based on the direction the device was pointing when device orientation was first requested. The included webkit offers you the compass heading. To make it work for all other browsers (which all supports alpha as compassheading) you can use the following Javascript code:
if (window.DeviceOrientationEvent) {
// Listen for the deviceorientation event and handle the raw data
window.addEventListener('deviceorientation', function(eventData) {
var compassdir;
if(event.webkitCompassHeading) {
// Apple works only with this, alpha doesn't work
compassdir = event.webkitCompassHeading;
}
else compassdir = event.alpha;
});
}
Android also supports Webkit, so would also use event.webkitCompassHeading, but that's OK.
BTW: "oncompassneedscalibration" is also not supported for iPhones and iPads.
I believe you can use the "heading" field of the location object, from navigator.geolocation, please see here:
https://developer.mozilla.org/en-US/docs/WebAPI/Using_geolocation
I know no other way.
Hope it helps,
A.
I am trying to change the display of my web pages depending on the version of the browser and space on screen. I need to completely change the look of the pages as follow:
If the site is displayed on a mobile phone I want the mini version.
If the site is displayed on a desktop browser but the size of the window is too small I want the mini version.
If the site is displayed on a desktop browser and the window can accommodate the full version I want the full version displayed.
If no javascript is available the full version should display.
I just started with some pretty basic code which relies on userAgent:
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) )
Is there a clean way to achieve what I'm trying to do with JQuery for example?
Use CSS media queries. Sniffing the user agent is not reliable, and will lead to maintenance headaches in the future. Also, using media queries means no javascript is required which is good from a separation of concerns point of view.
I have a website with a simple Flash animation behind some text and semi-transparent images as a background. I have used swfobject to embed it and set wmode opaque to make it display correctly in most browsers.
For browsers without Flash, the user gets a static background image instead and would not know they were missing anything. However, Android users get the flash background on top of everything as per the known issue with how Flash content is rendered in the Android browser making the site unusable.
I have added a crude browser sniff javascript function to the swfobject code to prevent it from loading for any user agent whith 'Mobile' in it:
<script type="text/javascript">
if (navigator.userAgent.indexOf('Mobile') == -1)
{
var flashvars = {};
var params = { wmode: "opaque" };
var attributes = {};
swfobject.embedSWF("Images/Layout/center_flash.swf", "flashBg",
"1004", "502", "9", "false", flashvars, params, attributes);
}
</script>
The only problem I have left is for Android users browsing with 'Mobile View' turned off as the user agent pretends to be a desktop version of Safari (I think). I do not wish to disable the Flash animation for all Safari users. Is there a way of blocking it for just Andriod users - even if they have 'Mobile View' disabled?
Possible ideas include:
detecting the Flash version with JavaScript or Flash. Does Android use specific versions (version numbers) of Flash which are different from the desktop equivalent?
blocking the specific user agents used by Android devices with 'Mobile View' disabled.
Has anyone come up with an effective workaround for this issue?
Your help/input is appreciated!
You can detect android only by checking the userAgent of the browser in your JavaScript
Something like this:
if (navigator.userAgent.toLowerCase().indexOf("android") != -1)
{
// It's android
}
As far as the flash issue itself, I don't know as I never use flash :P
edit
You can also use that technique for other useragents (I.E. iPhone, iPad, safari)
edit2
Sorry, I just went on my android phone and realized the actual setting changes the userAgent to whatever the user picks (desktop/ipad/iphone/safari). That's no good then, I apologize.
Unfortunately, what you are asking is very difficult then. There are no unique identifiers in the android flash version to give you any help. And the fact that android spoofs the userAgent makes it impossibly to detect if they are on mobile or not.
There exist services that can tell you whether a user is on mobile based on their IP.
I'm sorry to say I don't know how fast, reliable, or expensive they are, but if you must determine whether a user is on Android, that's an avenue to consider
The title explains itself. How can I detect if a web page has gone to background?
I'm implementing a chat application and I'll use this information to decide showing new message notifications. I suppose that GMail uses something like that. If the page is on background, it shows desktop notifications (on chrome), if not it doesn't show them.
I know that the answer has already been selected but I wanted to share another way.
You can use the hasFocus method on the document to see if it has the focus. There is no reason to set your own variable.
Here's some proof of concept code. jsFiddle is at the bottom. Every 3 seconds it will check if the window has focus or not–displaying true or false.
HTML:
<p>This will show if the document has focus every three seconds</p>
<button id="go">Go</button>
<button id="stop">Stop</button>
<ul id="active_log">
</ul>
CSS:
#stop { display: none; }
Javascript inside on document ready:
var timeout = null;
var checkActive = function() {
var isActive = window.document.hasFocus(),
$activity = $("<li />").text(isActive.toString());
$('#active_log').prepend($activity).find('li:nth-child(n+6)').fadeOut(function() {
$(this).remove();
});
timeout = setTimeout(checkActive, 3000);
}
$('#go').click(function() {
$(this).hide().siblings('button').show();
checkActive();
});
$('#stop').click(function() {
$(this).hide().siblings('button').show();
clearTimeout(timeout);
timeout = null;
});
http://jsfiddle.net/natedavisolds/2D7za/1/
There's now a page visibility API for this, and it is well-supported by all the most recent versions of major browsers on Windows, Mac OS X, and Linux (though I have not actually tested all browsers with a fair share of the Linux browser market).
The page visibility API is now the best approach for checking visibility; the only caveats are that it can't tell you what parts of the browser window are visible (just that nothing is visible or at least some part is), and that support has only been present since 2016 on Linux, 2015 on Mac, and 2014 (possibly earlier) on Windows.
While support was being rolled out, a false negative was rare, but false positives occurred on some platforms; for example, in 2014, OSX rendered miniature versions of minimized applications in the dock, and as a result of the way this had been done, an application could not easily tell whether it was minimized, as it was still asked to paint the screen. Linux had complications with knowing whether your application was on a non-visible workspace, and whether another window was occluding it.
The first public draft was published in June, 2011, and it reached "recommendation" status in May 2013. By March, 2014, the most recent versions of all major Windows browsers had full support for the standard. Full support for all major Mac browsers was achieved in April, 2015. Linux support was achieved for at least Chromium by August of 2016 (when Chromium issue 293128 was closed); while I have not tested them, I expect other Linux browsers have likely kept pace, as the hardest part of the work seems to have been adjusting OS/GUI tookit contracts and APIs to make knowing whether your desktop application is visible possible.
You can bind to window's blur and focus events. Here is a snippet code from an app I wrote:
$(window).bind("blur", function() {
Chatterbox.set_focused(false);
});
$(window).bind("focus", function() {
Chatterbox.set_focused(true);
});