46

This is related to the "fix" for position:fixed in older versions of iOS. However, if iOS5 or greater is installed, the fix breaks the page.

I know how to detect iOS 5: navigator.userAgent.match(/OS 5_\d like Mac OS X/i) but that won't work for iOS6 when it eventually comes around, or even iOS 5.0.1, only a 2 digit version.

So this is what I have atm.

$(document).bind("scroll", function() {
    if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i))) {
        if (navigator.userAgent.match(/OS 5_\d like Mac OS X/i)) {
    }
    else {
        changeFooterPosition();
    }
});
Ilmari Karonen
  • 44,762
  • 9
  • 83
  • 142
  • Have you tried feature-based detection instead of user agent sniffing? I found [this](https://github.com/Modernizr/Modernizr/issues/167) but I'm not able to test it currently. – kubetz Dec 01 '11 at 21:00
  • There's a script for testing by looking for support for position:fixed, but it's fairly complicated, and beyond my limited skills. And I think it would slow things down. – absynthe minded web smith Dec 01 '11 at 21:12
  • The problem of user agent sniffing is that http clients are often able to change their user-agent and you are hardcoding your fixes to limited number of browsers. Also the slow-down is minimal as it is something that should be executed only once and definitely not multiple times (like in event handlers). You don't need to understand that script. You don't understand everything you use in jQuery I guess :). – kubetz Dec 01 '11 at 21:18

9 Answers9

130

This snippet of code can be used to determine any version of iOS 2.0 and later.

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] >= 5) {
  alert('This is running iOS 5 or later.');
}
Peter T Bosse II
  • 1,491
  • 1
  • 10
  • 5
  • 1
    Thanks for coming up with this solution! The only thing I would change: https://gist.github.com/rafaelrinaldi/5873671 This way I'm able to do an actual numeric comparison instead of checking the string value of the first index of my result. –  Jun 27 '13 at 03:11
  • 4
    In my experience, an iPod touch actually returns "iPod touch" from `navigator.platform`, so I use the _RegExp_ `/iP(hone|od touch|ad)/` to catch it too. – ele Apr 28 '15 at 18:00
  • 2
    Chrome gives true for this also :( I suggest to add ``return -1`` after the if-statement – OZZIE Oct 06 '15 at 15:21
  • do you know what this would return on android devices? i just added 'else return null', so hopefully that can indicate a non-ios device – user1709076 Jul 18 '17 at 02:56
  • Really really helpful. I was looking to catch this bug and its reason since years. Thanks! – ddlab Jan 22 '19 at 13:06
  • To prevent console error "uncaught typeerror cannot read property '0' of undefined" in desktop browsers, [ie non ios] ADD "return false;" after first "if" statement ... return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)]; } else { return false; } – user1762289 Jul 24 '19 at 04:20
11

Pumbaa80's Answer was almost 100%, he just left out one part. Some iOS release have a third digit on them.

Example

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_us) AppleWebKit/525.18.1 (KHTML, like Gecko)

The follow allows for that

if(/(iPhone|iPod|iPad)/i.test(navigator.userAgent)) { 
    if(/OS [2-4]_\d(_\d)? like Mac OS X/i.test(navigator.userAgent)) {  
        // iOS 2-4 so Do Something   
    } else if(/CPU like Mac OS X/i.test(navigator.userAgent)) {
        // iOS 1 so Do Something 
    } else {
        // iOS 5 or Newer so Do Nothing
    }
}

That extra bit (_\d)? allows for the possibility of a third digit in the Version number. Charlie S, That should answer your question too.

Note the else because the 1st check won't work on iOS 1. iOS 1 for the iPhone and iPod didn't include a version number in its UserAgent string.

iPhone v 1.0

Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543 Safari/419.3

iPod v1.1.3

Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A93 Safari/419.3

All of this can be found at the following link on Apples website here.

JDubDev
  • 174
  • 1
  • 8
6

I could not really find what I was looking for, so I took ideas from this page and other pages around the net and came up with this. Hopefully others will find it useful as well.

function iOS_version() { 
    if(navigator.userAgent.match(/ipad|iphone|ipod/i)){ //if the current device is an iDevice
    var ios_info ={};
    ios_info.User_Agent=navigator.userAgent;
    ios_info.As_Reported=(navigator.userAgent).match(/OS (\d)?\d_\d(_\d)?/i)[0];
    ios_info.Major_Release=(navigator.userAgent).match(/OS (\d)?\d_\d(_\d)?/i)[0].split('_')[0];
    ios_info.Full_Release=(navigator.userAgent).match(/OS (\d)?\d_\d(_\d)?/i)[0].replace(/_/g,".");
    ios_info.Major_Release_Numeric=+(navigator.userAgent).match(/OS (\d)?\d_\d(_\d)?/i)[0].split('_')[0].replace("OS ","");
    ios_info.Full_Release_Numeric=+(navigator.userAgent).match(/OS (\d)?\d_\d(_\d)?/i)[0].replace("_",".").replace("_","").replace("OS ","");   //converts versions like 4.3.3 to numeric value 4.33 for ease of numeric comparisons
    return(ios_info);
    }
}

It allows you to get the major release and full release number either as a string or as a number for iOS.

Example User Agent String:

    Mozilla/5.0 (iPhone; CPU iPhone OS 6_1_3 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10B329

Usage:

var iOS=iOS_version();
console.log(iOS.Full_Release); //returns values in form of "OS 6.1.3"
console.log(iOS.Full_Release_Numeric); //returns values in form of 6.13
//useful for comparisons like if(iOS.Full_Release_Numeric >6.2)

console.log(iOS.Major_Release); //returns values in form of "OS 6"
console.log(iOS.Major_Release_Numeric); //returns values in form of 6
//useful for comparisons like if(iOS.Major_Release_Numeric >7)

console.log(iOS.As_Reported); //returns values in form of "OS 6_1_3"
console.log(iOS.User_Agent); //returns the full user agent string

In the case of the original question on this page, you could use this code in the following manner:

var iOS=iOS_version();
$(document).bind("scroll", function() {
    if(iOS){if(iOS.Major_Release_Numeric <5) {} 
    else {changeFooterPosition();}
    }
});   
Joshua A
  • 61
  • 1
  • 1
4

Adding on to Pumbaa80's answer. The version string might be 4_0, 5_0_1, 4_0_4, etc., and so testing against [1-4]_/d (a single underscore and number) isn't adequate. The JavaScript below is working for me for various sub-versions of iOS 3-5:

if (/(iPhone|iPod|iPad)/i.test(navigator.userAgent)) {
    if (/OS [1-4](.*) like Mac OS X/i.test(navigator.userAgent)) {
      // iOS version is <= 4.
    } else {
      // iOS version is > 4.
    }
  }
Charlie Schliesser
  • 6,763
  • 3
  • 40
  • 71
4

Here's a bit of JS to determine iOS and Android OS version.

Tested with actual user agent strings for iOS 4.3 to 6.0.1, and Android 2.3.4 to 4.2

var userOS;    // will either be iOS, Android or unknown
var userOSver; // this is a string, use Number(userOSver) to convert

function getOS( )
{
  var ua = navigator.userAgent;
  var uaindex;

  // determine OS
  if ( ua.match(/iPad/i) || ua.match(/iPhone/i) )
  {
    userOS = 'iOS';
    uaindex = ua.indexOf( 'OS ' );
  }
  else if ( ua.match(/Android/i) )
  {
    userOS = 'Android';
    uaindex = ua.indexOf( 'Android ' );
  }
  else
  {
    userOS = 'unknown';
  }

  // determine version
  if ( userOS === 'iOS'  &&  uaindex > -1 )
  {
    userOSver = ua.substr( uaindex + 3, 3 ).replace( '_', '.' );
  }
  else if ( userOS === 'Android'  &&  uaindex > -1 )
  {
    userOSver = ua.substr( uaindex + 8, 3 );
  }
  else
  {
    userOSver = 'unknown';
  }
}

Then to detect a specific version and higher, try:

if ( userOS === 'iOS' && Number( userOSver.charAt(0) ) >= 5 ) { ... }
Jim Bergman
  • 4,927
  • 2
  • 16
  • 19
3

First: Don't use match when a test is enough.

Second: You should test the other way round. Find the UAs which are known to be broken.

if(/(iPhone|iPod|iPad)/i.test(navigator.userAgent)) {
    if (/OS [1-4]_\d like Mac OS X/i.test(navigator.userAgent)) {
        changeFooterPosition();
...
user123444555621
  • 130,762
  • 25
  • 104
  • 122
1

Just simply run this code in device/browser

if(window.navigator.userAgent.match( /iP(hone|od|ad)/)){

    var iphone_version= parseFloat(String(window.navigator.userAgent.match(/[0-9]_[0-9]/)).split('_')[0]+'.'+String(window.navigator.userAgent.match(/[0-9]_[0-9]/)).split('_')[1]);

    // iPhone CPU iPhone OS 8_4 like Mac OS X

    alert(iphone_version); // its alert 8.4

    if(iphone_version >= 8){
       alert('iPhone device, iOS 8 version or greater!');
    }
}

This iphone_version variable will give you correct OS version for any iPhone device.

maSC0d3R
  • 161
  • 1
  • 3
  • 4
1
function getIOSVersion() {
    const ua = navigator.userAgent;
    if (/(iPhone|iPod|iPad)/i.test(ua)) {
        return ua.match(/OS [\d_]+/i)[0].substr(3).split('_').map(n => parseInt(n));
    }
    return [0];
}

This will return an array with the individual version numbers like [10,0,1] for v10.0.1, or it'll default to [0] otherwise. You can check the first digit (the major version) or all of them to test for the versions you need.

Mani Gandham
  • 5,581
  • 43
  • 54
0

Further parse out the version number ("5"), then add a condition where if number is greater than / less than version number.

Joshua
  • 3,605
  • 1
  • 24
  • 32
  • Something like? $(document).bind("scroll", function() { if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i))) { if (match = /iPhone OS (.*) like Mac OS X/.exec(navigator.userAgent)) { var version = parseInt(match[1].replace('_', ''), 10) / 100; if (version < 5) { changeFooterPosition(); } } } }); – absynthe minded web smith Dec 01 '11 at 21:22