This question already has answers here:
Detect iOS version less than 5 with JavaScript
(9 answers)
Closed 9 years ago.
I come across bugs with fixed positionning on iOs (fixed menu on bottom, coming on the middle of screen when the keyboard comes up).
The thing is, this bug only happens on iOs 6.1.4. So the fix i've just done works for iOs 6.1.4 (this one : http://dansajin.com/2012/12/07/fix-position-fixed/), but makes the menu coming to the middle on the screen on iOs 6.1.3...
Is there a way to detect the current version of iOs in JS ?
Have you tried using console.log(navigator); to grab information regarding the browsing machine?
navigator.userAgent or navigator.platform will provide you with the basis for what you need, that said I'm not so sure you'll be able to track it down to such a specific degree.
You can also try this snippet of code:
function iOSversion() {
if (/iP(hone|od|ad)/.test(navigator.platform)) {
// supports iOS 2.0 and later: <http://bit.ly/TJjs1V>
var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)];
}
}
ver = iOSversion();
if (/(iPad|iPhone|iPod)/g.test( navigator.userAgent ) && ver[0] == 6 && ver[1] ==1 && ver[2]==3) {
alert('This is running iOS 6.1.3 or later.');
}
Adapted from here
My recommendation would be always to attempt to fix the underlying issue rather than implement a workaround, however I appreciate this can sometimes be impractical.
According to this post the iOS version (above 2.0) can be found with:
function iOSversion() {
if (/iP(hone|od|ad)/.test(navigator.platform)) {
// supports iOS 2.0 and later: <http://bit.ly/TJjs1V>
var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)];
}
}
ver = iOSversion();
if (ver[0] === 6.14) {
alert('This is running iOS 6.14.');
}
Related
How can I reliably detect using javascript that a page is loaded inside a WKWebView? I'd like to be able to detect these scenarios:
iOS & WKWebView
iOS & Safari
not iOS
There is a similar question about UIWebView here. But it's quite old and I'm not sure if same still applies to WKWebView.
The accepted answer doesn't work as tested using the WKWebView vs UIWebView app
As the article mentions, the only HTML5 feature difference is IndexedDB support. So I'd go for a more reliable pattern with:
if (navigator.platform.substr(0,2) === 'iP'){
//iOS (iPhone, iPod or iPad)
var lte9 = /constructor/i.test(window.HTMLElement);
var nav = window.navigator, ua = nav.userAgent, idb = !!window.indexedDB;
if (ua.indexOf('Safari') !== -1 && ua.indexOf('Version') !== -1 && !nav.standalone){
//Safari (WKWebView/Nitro since 6+)
} else if ((!idb && lte9) || !window.statusbar.visible) {
//UIWebView
} else if ((window.webkit && window.webkit.messageHandlers) || !lte9 || idb){
//WKWebView
}
}
You may ask: Why not using the UserAgent? That's because Android browsers use it as settings! So, we should never trust any UAs. Only browser features and property checks as such.
Also I noticed that the QuickTime plugin was always loaded as part of Older Safari and other Browsers in UIWebView. But the plugin is no longer present in WKWebView. So you can use the QuickTime plugin presence as an extra check.
9/23/16 Edit: I adjusted the code for Safari 10 which no longer allowed the sole idb check to be reliable, as mentioned by #xmnboy. To discard Safari 10, it checks for the old webkit engine bug, which only applied until Safari 9.2; and i use a window.statusbar.visible fallback which appears to be a reliable indicator signal after a few comparison tests between iOS 9 and 10. (please check though)
Given the change in behavior to the UIWebView that was introduced by Apple in iOS 10, here's a new answer that combines the original response by #Justin-Michael and the follow-up favorite by #hexalys.
var isWKWebView = false ;
if( navigator.platform.substr(0,2) === 'iP' ) { // iOS detected
if( window.webkit && window.webkit.messageHandlers ) {
isWKWebView = true ;
}
}
It turns out that Justin's answer was really the better feature detection mechanism, because it works for both iOS 9 and iOS 10.
No telling what happens when we get to iOS 11. :-)
Qualification: this test will work if you are using the official Cordova WKWebView plugin to build your webview app, because that plugin does initialize the addScriptMessageHandler method, as noted by #hexalys in the comments to this post. That mechanism is being used by Cordova to define a new JS to native bridge when the WKWebView plugin is present.
Search for addScriptMessageHandler in that plugin repo and see the very end of the ios-wkwebview-exec.js file in that repo for some implementation details (or search for the string window.webkit.messageHandlers in that file).
In iOS, you could add this code to establish communication between javascript and objective-c:
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKUserContentController *controller = [[WKUserContentController alloc] init];
[controller addScriptMessageHandler:self name:#"javascript_observer"];
configuration.userContentController = controller;
...
webview = [[WKWebView alloc] initWithFrame:... configuration: configuration];
In javascript, you could test the connection like this:
if ( window.webkit != undefined ){
//javascript is running in webview
}
It seems that because the latest iOS Chrome uses WKWebView as a rendering engine, Chrome is detected as WKWebView.
ua.indexOf('CriOS') !== -1
will helps to distinguish Chrome from WKWebView in App.
You can check for the existence of window.webkit.messageHandlers which WKWebKit uses to receive messages from JavaScript. If it exists, you're inside a WKWebView.
That combined with a simple user agent check should do the trick:
var iOS = (navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? true : false);
var isWKWebView = false;
if (window.webkit && window.webkit.messageHandlers) {
isWKWebView = true;
}
When I use swfobject.getFlashPlayerVersion() on IE11 with flash version older than current 15.0.0, I always get "0.0.0" as the result. (with version 15 it works correctly)
I have tested it with both flash player plugin on FF and active x on IE. With Firefox, everything works correctly. Swfobject FAQ states in question 3 that some versions may give incorrect results, but it does not mention returning "0.0.0" and also I have tested flash player versions 9, 10, 10.2, 10.3, 11.3 and 13 and the result in IE was always the same.
I really need to get the correct version of flash player installed in IE. Is there any solution to this problem? Are there any other options how to reliably get the correct flash player version?
EDIT: There was a question what swfobject does to look up the version. Well this is the part of the code that does it:
if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
d = nav.plugins[SHOCKWAVE_FLASH].description;
if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
plugin = true;
ie = false; // cascaded feature detection for Internet Explorer
d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
}
}
else if (typeof win.ActiveXObject != UNDEF) {
try {
var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
if (a) { // a will return null when ActiveX is disabled
d = a.GetVariable("$version");
if (d) {
ie = true; // cascaded feature detection for Internet Explorer
d = d.split(" ")[1].split(",");
playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
}
}
}
catch(e) {}
}
I found out that in IE10 it goes to the else if part (flash version does not matter) while in IE11 with flash 15 it goes to the first if . However, with IE11 and older flash it skips both conditions:
window.ActiveXObject is undefined in IE11 (as it should be, or at least that's what I have found)
but it also skips the first if and when I look at navigator.plugins there aren't any despite having the flash 11.0 installed
Where is the problem? Why the older flash is not listed in my IE11 plugins?
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to programmatically get iOS’s alphanumeric version string
Is there any future proof regex to get the version number of the following smartphone OS's from the user-agent?
Android
(I have found something like: /Androids+([d.]+)/ )
iOS
BlackBerry
Any advise would be much appreciated.
Clarification: Seems like the question is asking how to get the mobile device OS version in a web-app, probably using JS.
UPDATE:
After I got quite bashed to ask this question I want at least provide the solution I came up with:
supportedDevice: function() {
var supportedDevice = false;
var userAgent = window.navigator.userAgent;
// check for supported Android device
if ( /Android/.test(userAgent) ) {
var a_index = Number(userAgent.indexOf('Android')) + 8;
var a_version = +userAgent.substring(a_index, a_index+1);
if ( a_version >= 3 ) {
supportedDevice = true;
console.log('Android device supported!')
}
}
// check for iOS supported devices
else if ( /iPhone/.test(userAgent) ) {
var i_index = Number(userAgent.indexOf('iPhone OS')) + 10;
var i_version = +userAgent.substring(i_index, i_index+1);
if ( i_version >= 6 ) {
supportedDevice = true;
console.log('iPhone device supported!')
}
}
// check for iOS supported devices
else if ( /BlackBerry/.test(userAgent) ) {
var b_index = Number(userAgent.indexOf('Version/')) + 8;
var b_version = +userAgent.substring(b_index, b_index+1);
if ( b_version >= 6 ) {
supportedDevice = true;
console.log('BB device supported!')
}
}
return supportedDevice;
}
If you need to obtain the version number in a web app, your best bet would be to use the device User Agent and parse out the version number. A more robust method would be to look up the user agent in the WURFL database to obtain the device characteristics and the corresponding OS. The first method is simpler.
If you are using an app, most OS SDKs provide APIs to identify the version of the OS running on the device
I need a method to detect that the browser is Safari 5 or higher - but the javascript should not rely on useragent since it can get overriden! Any ideas?
I have found PPK's browser detection code to be very reliable. It utilizes navigator.vendor and navigator.userAgent.
It's not possible to reliably detect the browser without accepting that the user agent can be modified by the end-user and / or the browser itself.
As a consequence of point 1. it is almost always best to use capabilities support detection (e.g. such as with Modernizr).
As there are times when you need to specifically detect a browser, such as disabling or enabling a particular capability that is misreported / not detectable, e.g. File Drag and Drop in Safari 5
As an example, the following code provides a function isFileDragAndDropSupported() which makes use of the isSafari5() function to return that File Drag and Drop is supported on Safari 5 even though window.FileReader is not defined in Safari 5.
function isSafari5() {
return !!navigator.userAgent.match(' Safari/') && !navigator.userAgent.match(' Chrom') && !!navigator.userAgent.match(' Version/5.');
};
function isFileAPIEnabled () {
return !!window.FileReader;
};
function isFileDragAndDropSupported() {
var isiOS = !!navigator.userAgent.match('iPhone OS') || !!navigator.userAgent.match('iPad');
return (Modernizr.draganddrop && !isiOS && (isFileAPIEnabled() || isSafari5()));
};
Note: Modernizr is required only for the isFileDragAndDropSupported() function. The isSafari5() function will work stand-alone.
Amazon.com recently updated their javascript, and it's causing problems with some Opera browsers.
Their browser detection code looks like so, but it's faulty:
function sitbReaderIsCompatibleBrowser() {
if (typeof(jQuery) == 'undefined') {
return false;
} else {
var version = jQuery.browser.version || "0";
var splitVersion = version.split('.');
return (
(jQuery.browser.msie && splitVersion[0] >= 6) // IE 6 and higher
|| (jQuery.browser.mozilla && (
(splitVersion[0] == 1 && splitVersion[1] >= 8) // Firefox 2 and higher
|| (splitVersion[0] >= 2)
))
|| (jQuery.browser.safari && splitVersion[0] >= 500) // Safari 5 and higher
|| (jQuery.browser.opera && splitVersion[0] >= 9) // Opera 5 and higher
);
}
}
Nothing obviously wrong jumps out at me with this code, but I've never used jQuery before so I don't know.
Even though this code looks like it's attempting to let Opera users through, when I visit the page with Opera 9.64 I get an "unsupported browser" message. If I change Opera's settings to report itself as Firefox, the page works perfectly! With that in mind, I'm pretty sure it's a problem with the script and not the browser.
Any jQuery experts have a suggestion?
You can replicate the behavior by visiting any book on Amazon and clicking the "look inside this book" link.
Prior to jQuery 1.3, you could use jQuery.browser:
if( $.browser.opera ){
alert( "You're using Opera version "+$.browser.version+"!" );
}
From version 1.3, you should use jQuery.support instead.
Main reason for this is that should should avoid checking for browsers, as features may change from version to version, making your code obsolete in no time.
You should always try to use feature detection instead. This will allow you to see if current browser supports the feature you're trying to use, regardless the browser brand, version, etc.
There is a special window.opera object which is present in all Opera 5+ browsers. So something as simple as:
if (window.opera && window.opera.buildNumber) {
// we are in Opera
}
would be enough.
I check for Opera like this:
if (/Opera/.test (navigator.userAgent)) // do something
Why would you want jQuery?
It is much better to detect javascript capabilities rather than browser userAgent.
ie DOM, XmlHttpRequest, eventing model (event.target vs event.srcElement), ActiveX, Java etc
By focusing on the API functions that you will require, rather than a target browser you will create a more robust set of scripts, and inevitably less special casing.
This link here at opera will probably tell you more
A very simple way from Opera themselves:
if (window.opera) {
//this browser is Opera
}
Source: http://my.opera.com/community/openweb/idopera/
The main reason why Amazon fails on Opera is because the send different code from the server side already... If you visit the same page with Firefox and then save that page and reopen it in Opera it works fine...
But they promised to fix that sometime in January...
I think this way is the best
if ( window.opera.version() == 12) {
}
This example check if opera version is 12. Very useful when I have problems with font-face in Opera.
I don't know for sure ( i never really check for opera anyway) but if the built-in jQuery functionality doesn't detect opera, may be a bug with the jQuery which needs to be fixed. I would suspect if that's the case, it should get resolved fairly quickly.
In current HTML5 times, you can also check for browser features instead often.
if (!window.FormData) { alert("xmlhttprequest L2 FormData interface not available"); }