64

I had several clients complain yesterday that some code stopped working. Apparently it comes down to plug-ins using the now deprecated jQuery.browser which stopped working yesterday when jQuery 1.9 was released.

I (quickly) looked at the 1.9 change docs and it seems like they want me to substitute some pretty heavy libraries just for that one function.

Is there a recommended lightest weight plug-in or code snippet to restore that functionality?

For what these sites need, it's very basic; I only need the most basic detection of IE vs FF vs everyone else.

Suggestions?

Eonasdan
  • 7,563
  • 8
  • 55
  • 82
jchwebdev
  • 5,034
  • 5
  • 21
  • 30
  • 7
    To cite the five-year-old message from the jQuery docs: "We recommend against using this property; please try to use feature detection instead (see jQuery.support). jQuery.browser may be moved to a plugin in a future release of jQuery." http://api.jquery.com/jQuery.browser/ VS. http://api.jquery.com/jQuery.support/ – feeela Jan 16 '13 at 19:03
  • use `>1.8` ,`<1.9` lesser jQuery. – Jai Jan 16 '13 at 19:15
  • 4
    Thanks. I understand it was marked for deprecation. I have several plugs that depend on the .offsetTop property -- which keeps returning a different value for various browsers. I found that just checking for IE vs. Mozilla vs. Chrome was an easy workaround. If offsetTop was consistent I wouldn't need this at all. – jchwebdev Jan 16 '13 at 20:48

13 Answers13

40

I've use the following code answered by Alexx Roche, but i wanted to detect MSIE so:

<script type="text/javascript">
   $(document).ready(function() {
      if (navigator.userAgent.match(/msie/i) ){
        alert('I am an old fashioned Internet Explorer');
      }
   });
</script>

hope it helps!

Fede
  • 557
  • 6
  • 8
  • 10
    If you want to catch newer IE:s too, add a check for "trident" too like so: `if (navigator.userAgent.match(/msie|trident/i)) {;}` – Martin Andersson Nov 30 '13 at 19:13
23

jQuery Migrate was created to allow for backwards compatibility while you update your code.

https://github.com/jquery/jquery-migrate

As a bonus, it logs deprecated functions as you use them. I would give it a try while you resolve the problems. Also, you should be setting a specific version of jQuery for your sites. It's good to upgrade, but be sure to test those upgrades before putting them in production. If you are using a CDN, you can still specify a specific version in the file name.

Now, you don't need a jQuery plugin for what you are asking. Check out the navigator object.

appCodeName: "Mozilla"
appName: "Netscape"
appVersion: "5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17"
cookieEnabled: true
doNotTrack: null
geolocation: Geolocation
language: "en-US"
mimeTypes: MimeTypeArray
onLine: true
platform: "MacIntel"
plugins: PluginArray
product: "Gecko"
productSub: "20030107"
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17"
vendor: "Google Inc."
vendorSub: ""
Brad
  • 159,648
  • 54
  • 349
  • 530
  • 1
    Thanks. I will probably just use navigator. Some of my clients are sites I've taken over from other devs and this is the kind of thing that slips through the cracks. (My cracks, anyway). – jchwebdev Jan 16 '13 at 20:50
  • Next stupid question... I just tried Navigator in Firebug and Chrome Console. And both show Netscape as appName and Mozilla as appCodeName. And 'Vendor' is Mozilla on FF but blank on Chrome. So... is there a -simple- 'trick' or is this (another) fairly complex topic with no 2-3 lines of code answer? – jchwebdev Jan 16 '13 at 20:58
  • 1
    You should try using the accept answer button on occasion as well. – teynon Jan 16 '13 at 20:58
  • 1
    @jchwebdev, I would look at `navigator.userAgent`. It should be easy enough to see if the string contains what you're looking for. (Don't look for exact matches, as obviously version numbers and plugins change.) – Brad Jan 16 '13 at 21:12
  • Thanks, Brad. I was a bit frustrated earlier. I thought all the 'browser war' junk was -mostly- over. – jchwebdev Jan 16 '13 at 21:39
  • var browser = { chrome: false, mozilla: false, opera: false, msie: false, safari: false }; var sBrowser, sUsrAg = navigator.userAgent; if(sUsrAg.indexOf("Chrome") > -1) { browser.chrome = true; } else if (sUsrAg.indexOf("Safari") > -1) { browser.safari = true; } else if (sUsrAg.indexOf("Opera") > -1) { browser.opera = true; } else if (sUsrAg.indexOf("Firefox") > -1) { browser.mozilla = true; } else if (sUsrAg.indexOf("MSIE") > -1) { browser.msie = true; } console.log(browser.msie); – user989952 May 07 '13 at 01:38
22
var browser = {
        chrome: false,
        mozilla: false,
        opera: false,
        msie: false,
        safari: false
    };
    var sUsrAg = navigator.userAgent;
    if(sUsrAg.indexOf("Chrome") > -1) {
        browser.chrome = true;
    } else if (sUsrAg.indexOf("Safari") > -1) {
        browser.safari = true;
    } else if (sUsrAg.indexOf("Opera") > -1) {
        browser.opera = true;
    } else if (sUsrAg.indexOf("Firefox") > -1) {
        browser.mozilla = true;
    } else if (sUsrAg.indexOf("MSIE") > -1) {
        browser.msie = true;
    }
    console.log(browser.msie);
GoldDragonTSU
  • 487
  • 1
  • 9
  • 23
user989952
  • 661
  • 1
  • 12
  • 23
  • This is awesome. Very thorough and exactly what I needed. Going to add some version tests to this as well so that I can target IE9. Thanks for the awesome hack! – Tabetha Moe Jul 06 '13 at 02:23
11

Put this code in your site (like js file, or after code of jQuery...):

var matched, browser;

// Use of jQuery.browser is frowned upon.
// More details: http://api.jquery.com/jQuery.browser
// jQuery.uaMatch maintained for back-compat
jQuery.uaMatch = function( ua ) {
    ua = ua.toLowerCase();

    var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
        /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
        /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
        /(msie) ([\w.]+)/.exec( ua ) ||
        ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
        [];

    return {
        browser: match[ 1 ] || "",
        version: match[ 2 ] || "0"
    };
};

matched = jQuery.uaMatch( navigator.userAgent );
browser = {};

if ( matched.browser ) {
    browser[ matched.browser ] = true;
    browser.version = matched.version;
}

// Chrome is Webkit, but Webkit is also Safari.
if ( browser.chrome ) {
    browser.webkit = true;
} else if ( browser.webkit ) {
    browser.safari = true;
}

jQuery.browser = browser;
Synthy
  • 160
  • 5
  • 2
    This answer would be improved if it referenced [the maintained origin](https://github.com/jquery/jquery-migrate/blob/master/src/core.js), and noting that it is [MIT-licensed](https://github.com/jquery/jquery-migrate/blob/master/LICENSE-MIT). – Brian M. Hunt Feb 08 '13 at 02:42
  • 4
    I suppose it's good for points and rep here, but telling people to copy/pasta the deprecated functionality doesn't address the issues that caused us to deprecated `$.browser` in the first place. And yes, the copy/pasta needs to respect the licensing terms. – Dave Methvin Feb 10 '13 at 18:47
  • I added a small Hotfix for IE11 detection to @Synthy code. `// hofix for IE11 detection var isIE11 = !!navigator.userAgent.match(/Trident\/7\./); if (isIE11) { browser.msie = "true"; delete browser.mozilla; }` – chris Nov 14 '13 at 08:12
  • @DaveMethvin That is certainly true, but when you just want to get some other simple plugin working and you don't feel like figuring out what that plugin is doing that requires .browser to work, this is definitely the simplest fix. (Including all of jquery.migrate is both overkill, and also had other odd side-effects that I don't feel like trying to figure out why that was happening, either. This was all I needed!) – neminem Nov 15 '13 at 23:30
10

I've used the following code when I hit the same issue:

<script type="text/javascript">
 $(document).ready(function() {
    //if (!$.browser.webkit && ! $.browser.mozilla) { //depricated
    if (!navigator.userAgent.match(/mozilla/i) && 
        ! navigator.userAgent.match(/webkit/i) ){
        alert('Let me tell you about Mozilla');
    }
 });
</script>
Alexx Roche
  • 3,151
  • 1
  • 33
  • 39
  • 1
    what exactly is this supposed to check? because (!navigator.userAgent.match(/mozilla/i) && !navigator.userAgent.match(/webkit/i) ) is false in IE, Chrome and Mozilla – Matus Jun 09 '13 at 09:26
  • Yes, because in this situation I only wanted the jQuery functionality in the browsers that supported it. Pulling the pling (!) or changing && to || should be easy enough for anyone up to their elbows in jQuery? – Alexx Roche Jun 10 '13 at 10:02
  • no problem, I was just surprised that the marked answer didn't answer the OP's question – Matus Jun 10 '13 at 12:28
6

You could just not update until you move away from depreciated methods.

You really shouldn't be including jquery from a CDN without specifying a version number anyway, it in a way defeats the purpose of using a CDN (no cacheing).

Here's a link to the latest version of jQuery that supported $.browser:

http://code.jquery.com/jquery-1.8.3.min.js

simply replace your jquery.js src with that link and your code will continue to run until you are ready to move forward and stop using depreciated features.

Note: Fancybox2 still uses $.browser, that's the most common one I've seen so far since the update.

Update: Slickgrid is still using $.browser, no update as of 02/11/2013

Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • the `-latest` versions and wildcard versions will no longer be updated, you should not use them anymore. – Kevin B Jul 25 '14 at 15:13
6

I abstracted the logic from jQuery.browser into a plugin jquery.browser. The plugin is released under the MIT license.

I've also added support for IE11, Opera Webkit and Android detection.

Gabriel Cebrian
  • 395
  • 1
  • 3
  • 15
  • 1
    Thank you. I had just cobbled together my own plugin from pre-1.9 jQuery source code, then I found yours, which has useful extensions while acting as a perfect, drop-in replacement for the original functionality. – Lambart Dec 14 '13 at 23:12
2

Try Conditionizr

Hope this Helps :)

Ijas Ameenudeen
  • 9,069
  • 3
  • 41
  • 54
2

Exact version of IE can be detected by additional checking of existence of standard global objects added in specific IE versions.

10 or older document.all
9 or older  document.all && !window.atob
8 or older  document.all && !document.addEventListener
7 or older  document.all && !document.querySelector
6 or older  document.all && !window.XMLHttpRequest
5.x document.all && !document.compatMode

if (document.all && !document.querySelector) {
    alert('IE7 or lower');
}

These tests avoid using the userAgent which is used for spoofing

1
if(!$.browser){
    $.browser={chrome:false,mozilla:false,opera:false,msie:false,safari:false};
    var ua=navigator.userAgent;
        $.each($.browser,function(c,a){
        $.browser[c]=((new RegExp(c,'i').test(ua)))?true:false;
            if($.browser.mozilla && c =='mozilla'){$.browser.mozilla=((new RegExp('firefox','i').test(ua)))?true:false;};
            if($.browser.chrome && c =='safari'){$.browser.safari=false;};
        });
};

http://jsfiddle.net/R3AAX/3/

etb
  • 21
  • 2
  • 1
    For completeness, jQuery plugins should refer to 'jQuery' rather than '$', since other libraries might overwrite the $ shortcut. – Ben Hull Sep 03 '13 at 11:56
1

If all you want is your 3rd party jQuery plugins to be able to use jQuery.browser.msie, here's a one-liner. Just include it after jQuery.

jQuery.browser = jQuery.browser || {msie: navigator.userAgent.match(/msie/i) ? true : false};

This is the dumbest-possible fix, but it's all I needed, and it does work, so here you go!

Ben Hull
  • 7,524
  • 3
  • 36
  • 56
1

To add to this discussion. I just came up with a jquery $.browser plugin that, instead of 'detection', just merely parses the user agent into an easy-to-use object. Further logic can easily be applied to further break down and parse specific browsers and platforms.

I have had very reliable results on useragents found here: UserAgentString.com. I even included the version detection for ie11 (near the bottom).

//The following code is by no means perfect, nor is it meant to be a standalone 'detection' plugin. 
//It demonstrates parsing the useragent string into an easy to manage object. 
//Even if it does make detection rediculously easy.. :)

//Because this regex makes no assumptions in advance.
//IMO, It's compatibilty and maintainability is much higher than those based on static identifiers.

/*
  uaMatch replacement that parses a useragent string into an object
  useragent segments can be Name Value OR Name/Value OR Name

  Segment: Name Value
    Name: parsed to the last whitespace character
    Value: value after the last whitespace character
    Matches: (.NET CLR) (#.##), Android 2.3.4, etc
    Note: this regex can have leading/trailing whitespace (trimmed for object properties)

  Segment: Name/Value
    Matches: all values matching Name/Value
    Example: Firefox/24.0, Safari/533.1, Version/12.1, etc

  Segment: Name
    Matches: identifiers that hold no values (value of 'true' is implied)
    Example: Macintosh, Linux, Windows, KHTML, U, etc


   WARNING: not necessarily compatible with jQuery's $.browser implementation.
   - not recommended as a replacement for plugins that require it to function.
*/
(function ($) {

    var ua = navigator.userAgent.toLowerCase();

    var regex = /compatible; ([\w.+]+)[ \/]([\w.+]*)|([\w .+]+)[: \/]([\w.+]+)|([\w.+]+)/g;
    var match = regex.exec(ua);

    var browser = { };

    while (match != null) {
        var prop = {};

        if (match[1]) {
          prop.type = match[1];
          prop.version = match[2];
        }
        else if (match[3]) {
          prop.type = match[3];
          prop.version = match[4];
        }
        else {
          prop.type = match[5];
        }

        // some expressions have leading whitespace (i couldn't avoid this without a more complex expression)
        // trim them and get rid of '.' (' .NET CLR' = 'net_clr') 
        prop.type = $.trim(prop.type).replace(".","").replace(" ","_"); 
        var value = prop.version ? prop.version : true;

        if (browser[prop.type]) {
            if (!$.isArray(browser[prop.type]))
                browser[prop.type] = new Array(browser[prop.type]);

            browser[prop.type].push(value);
        }    
        else browser[prop.type] = value;

        match = regex.exec(ua);
    }

    for (var i in browser)
        if (i.indexOf("mac") > -1)
            browser.mac = true;

    if (browser.windows_nt && !browser.windows)
        browser.windows = true;

    //put known browsers into the 'version' property for 'some' jquery compatibility

    //for sake of argument chromium 'is' chrome
    if (browser.chromium && !browser.chrome)
        browser.chrome = browser.chromium;

    //chrome / safari / webkit
    if (browser.chrome) {
        browser.version = browser.chrome;
    }
    else if (browser.safari) {
        browser.version = browser.safari;
    }
    else {
        if (browser.applewebkit)
            browser.webkit = browser.applewebkit;

        if (browser.webkit)
            browser.version = browser.webkit;
    }

    //firefox / gecko
    if (browser.firefox) {
        if (browser.rv)
            browser.version = browser.rv;

        else browser.version = browser.firefox;
    }
    else if (browser.gecko) {
        if (browser.rv)
            browser.version = browser.rv;

        else browser.version = browser.gecko;
    }

    //opera
    if (browser.opera && !browser.version)
        browser.version = browser.opera;

    //msie
    if (browser.trident && browser.rv) //ie11
        browser.msie = browser.rv;

    if (browser.msie)
        browser.version = browser.msie;

    $.browser = browser;//Rename to reduce confliction?

    //WAS USED FOR TESTING & DISCOVERY (very useful)
    //TODO: remove line below
    alert(JSON.stringify($.browser));

}) (jQuery);

On Internet Explorer 10, JSON.stringify will ouput something like this:

{"mozilla":"5.0","msie":"10.0","windows_nt":"6.2","trident":"6.0","net4.0e":true,"net4.0c":true,"net_clr":["3.5.30729","2.0.50727","3.0.30729"],"windows":true,"version":"10.0"}
SilverX
  • 1,509
  • 16
  • 18
1

Short and yet Powerful.

// chrome, safari, webkit, mozilla, msie, opera
var chrome = /chrome/i.test(navigator.userAgent); 
Victor
  • 914
  • 12
  • 15
  • Can you explain the syntax? I haven't come across this structure? TIA, /chrome/ – jchwebdev Jul 09 '14 at 17:01
  • @jchwebdev sure: var chrome [bool] /chrome/ [string which we're searching in UA] i [case-insensitive] test [method] (navigator.userAgent) [returns UA string for the current browser] So you could check is it safari,mozilla, etc.. – Victor Jul 10 '14 at 13:41