How to detect browser using angularjs?

137,911

Solution 1

Like Eliran Malka asked, why do you need to check for IE 9?

Detecting browser make and version is generally a bad smell. This generally means that you there is a bigger problem with the code if you need JavaScript to detect specific versions of browser.

There are genuine cases where a feature won't work, like say WebSockets isn't supported in IE 8 or 9. This should be solved by checking for WebSocket support, and applying a polyfill if there is no native support.

This should be done with a library like Modernizr.

That being said, you can easily create service that would return the browser. There are valid cases where a feature exists in a browser but the implementation is outdated or broken. Modernizr is not appropriate for these cases.

app.service('browser', ['$window', function($window) {

     return function() {

         var userAgent = $window.navigator.userAgent;

        var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer/i};

        for(var key in browsers) {
            if (browsers[key].test(userAgent)) {
                return key;
            }
       };

       return 'unknown';
    }

}]);

Fixed typo broswers

Note: This is just an example of how to create a service in angular that will sniff the userAgent string. This is just a code example that is not expected to work in production and report all browsers in all situations.

UPDATE

It is probably best to use a third party library like https://github.com/ded/bowser or https://github.com/darcyclarke/Detect.js. These libs place an object on the window named bowser or detect respectively.

You can then expose this to the Angular IoC Container like this:

angular.module('yourModule').value('bowser', bowser);

Or

detectFactory.$inject = ['$window'];
function detectFactory($window) {
    return detect.parse($window.navigator.userAgent);
} 
angular.module('yourModule').factory('detect', detectFactory);

You would then inject one of these the usual way, and use the API provided by the lib. If you choose to use another lib that instead uses a constructor method, you would create a factory that instantiates it:

function someLibFactory() {
    return new SomeLib();
}
angular.module('yourModule').factory('someLib', someLibFactory);

You would then inject this into your controllers and services the normal way.

If the library you are injecting does not exactly match your requirements, you may want to employ the Adapter Pattern where you create a class/constructor with the exact methods you need.

In this example we just need to test for IE 9, and we are going to use the bowser lib above.

BrowserAdapter.$inject = ['bowser']; // bring in lib
function BrowserAdapter(bowser) {
    this.bowser = bowser;
}

BrowserAdapter.prototype.isIe9 = function() {
    return this.bowser.msie && this.browser.version == 9;
}

angular.module('yourModule').service('browserAdapter', BrowserAdapter);

Now in a controller or service you can inject the browserAdapter and just do if (browserAdapter.isIe9) { // do something }

If later you wanted to use detect instead of bowser, the changes in your code would be isolated to the BrowserAdapter.

UPDATE

In reality these values never change. IF you load the page in IE 9 it will never become Chrome 44. So instead of registering the BrowserAdapter as a service, just put the result in a value or constant.

angular.module('app').value('isIe9', broswerAdapter.isIe9);

Solution 2

Angular library uses document.documentMode to identify IE . It holds major version number for IE, or NaN/undefined if User Agent is not IE.

/**
* documentMode is an IE-only property
* http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
*/
var msie = document.documentMode;

https://github.com/angular/angular.js/blob/v1.5.0/src/Angular.js#L167-L171

Example with $document (angular wrapper for window.document)

// var msie = document.documentMode;
var msie = $document[0].documentMode;
// if is IE (documentMode contains IE version)
if (msie) {
  // IE logic here

  if (msie === 9) {
    // IE 9 logic here

  }
}

Solution 3

you should use conditional comments

<!--[if IE 9]>
<script type="text/javascript">
    window.isIE9 = true;
</script>
<![endif]-->

You can then check for $window.isIE9 in your controllers.

Solution 4

Not sure why you specify that it has to be within Angular. It's easily accomplished through JavaScript. Look at the navigator object.

Just open up your console and inspect navigator. It seems what you're specifically looking for is .userAgent or .appVersion.

I don't have IE9 installed, but you could try this following code

//Detect if IE 9
if(navigator.appVersion.indexOf("MSIE 9.")!=-1)

Solution 5

You can easily use the "ng-device-detector" module.

https://github.com/srfrnk/ng-device-detector

var app = angular.module('myapp', ["ng.deviceDetector"]);
app.controller('DeviceCtrl', ["$scope","deviceDetector",function($scope,deviceDetector) {
      console.log("browser: ", deviceDetector.browser);
      console.log("browser version: ", deviceDetector.browser_version);
      console.log("device: ", deviceDetector.device);
}]);
Share:
137,911
seUser
Author by

seUser

Updated on July 08, 2022

Comments

  • seUser
    seUser almost 2 years

    I am new to angularjs. How can I detect userAgent in angularjs. Is it possible to use that in controller? Tried something like below but no luck!

      var browserVersion = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
    

    I need to detect IE9 specifically!

  • EnigmaRM
    EnigmaRM about 10 years
    typo in forEach: broswers, replace with browsers
  • EnigmaRM
    EnigmaRM about 10 years
    This is a pretty good solution @Martin. Makes navigator a bit friendly.
  • Mohit Tanwani
    Mohit Tanwani almost 10 years
    Two further problems: 1. The angular.forEach() loop won't work, as it just loops through every item. Better off with an old-fashioned for...in construct. 2. The regex /internet explorer/i won't detect IE 11 and the code instead reports it as Chrome, see stackoverflow.com/questions/17907445/how-to-detect-ie11 Searching for /trident/i I believe works for all versions of IE compatible with Angular. For now.
  • Michael
    Michael almost 10 years
    If you have IE10 or IE11 installed you can use IE's F12 feature to render as IE9.
  • netzaffin
    netzaffin over 9 years
    Sometimes browsers implement the same features with different behaviours (e.g. placeholder hides on focus OR keydown). So you have to walkt this way
  • Michael
    Michael over 9 years
    OP said: I need to detect IE9 specifically!
  • Thanh Nguyen Van
    Thanh Nguyen Van over 9 years
    Worked for me. Thanks!
  • Martin
    Martin over 9 years
    Monkey patching angular is considered a bad practice.
  • brabertaser19
    brabertaser19 about 9 years
    bad smell, but for example ie < 10 didn't support file api etc
  • Martin
    Martin about 9 years
    @Brabertaser1992, yes. I agree this shouldn't be done. It is a bad smell. But if you are going to do it, move it to a service.
  • xrd
    xrd about 9 years
    The latest version of Chrome reports this: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36". So, depending on the order in which your forEach statement retrieves keys, it can return different results.
  • Admin
    Admin about 9 years
    Yes Martin, we can instead window.angular by another variable. No need window.angular
  • Huangism
    Huangism almost 9 years
    There are many cases where you need to detect browser make and version. I will give you the most practical use. I work for a big company that has a website which only supports say IE 10+ and they want a browser upgrade message to show when IE 9 and down. Eliran Malka said why detect using angular but not detection in general
  • Alain Duchesneau
    Alain Duchesneau over 8 years
    Sorry, may be a duplicate answer from Bohdan but with some extra…
  • usumoio
    usumoio about 8 years
    Thank you for explaining why this is bad practice But also explaining how this can be done. Excellent post.
  • Bohdan Lyzanets
    Bohdan Lyzanets about 8 years
    or $document[0] instead $window.document
  • Matt Andrzejczuk
    Matt Andrzejczuk about 8 years
    "Detecting browser make and version is generally a bad smell." No it doesn't when you consider that the purpose of detecting the browser version 99 out of 100 times it is intended for the abomination that is Internet Explorer. In my 6 years of web development, I've only needed this feature because of Internet Explorer, due to IE pretending to be Mozilla since 1995, that goes to show you that it's Microsoft's fault, not the web developer's.
  • ThisClark
    ThisClark almost 8 years
    Several times I come across large complicated answers with regular expression testing on window.navigator etc. When it is only IE we wish to defeat, this appears to be the singular best way.
  • Ringo
    Ringo over 7 years
    it is so cliche to call browser-sniffing a "bad smell"
  • peteallen
    peteallen over 7 years
    I also disagree with the "bad smell" comment, to an extent. While it may be true in many cases, there are many other cases where it's impractical or not in line with business priorities to support old browsers, so a decision is made to stop wasting time and cut off support for old browsers. In your websockets example, how far back do we go? Should I be trying to create a polyfill to provide support for old versions of Netscape? Or is it reasonable to say that people shouldn't be using IE 8 (and most people aren't) and I'm not going to support the few who still do?
  • luQ
    luQ almost 7 years
    Hey, thx for your anser. Could you pls be so kind and provide a code snippet or a link for further reading?
  • Sohail Faruqui
    Sohail Faruqui over 6 years
    thanks for the explanation, how can I add it to my project, there is no npm or bower support,
  • knickum
    knickum almost 6 years
    A few people are missing the "why" regarding the mentioned code smell. First, just to get on the same page, code smell is not a problem of itself, it's possibly indicative of a deeper problem -- why and how, here. Why are you browser sniffing? In many cases, to find if a feature is supported. So just check if that feature is supported (e.g. Modernizr). How are you sniffing? Look at the issues people are encountering in the comments with false positives or false negatives. It's not an impossible task, but maybe there's a better way to accomplish what you want i.e. it smells.
  • speciesUnknown
    speciesUnknown over 5 years
    Despite the obvious problems, I continue to have to detect browser - browser vendors intentionally make their browsers behave differently and this causes browser specific bugs. Consider IE with its additional caching (even in the presence of a no-cache header) or chrome with its autoplay policy.
  • Nick Patterson
    Nick Patterson almost 5 years
    Good reason to detect browser: you can open a file on a share with IE11 (file://) but you can't using Chrome. Nice to have a popup for chrome users saying that they have to use IE if they want to edit a file.