Making a Browser Sniffer for mf

This is a series of posts that explains some of the fundamental rules for developing complex JavaScript applications and the mf framework.

One of the first key things that is required in any JavaScript framework is a browser sniffer. Browser sniffers are easy to create and as with all of the modules that will be placed into mf it uses my standard design pattern. Here is the code:

var browser = Object.freeze((function(){
     var app = new String(navigator.userAgent),
     mode = document.documentMode,
     isIE = app.match('MSIE')!==null,
     isSafari = app.match('Safari')!==null && app.match('Chrome')===null,
     isChrome = app.match('Safari')!==null && app.match('Chrome')!==null,
     isFireFox = app.match('Firefox')!==null,
     tests = {
           isSafari : isSafari,
           isChrome : isChrome,
           isFireFox : isFireFox,
           isIE : isIE,
           isIE5 : isIE && mode===5,
           isIE6 : isIE && mode===6,
           isIE7 : isIE && mode===7,
           isIE8 : isIE && mode===8,
           isIE9 : isIE && mode===9,
           isIE10 : isIE && mode===10,
           version : 0,
           isWin : navigator.platform.toLowerCase()==='win32',
           isMac : navigator.platform.toLowerCase()!=='win32',
           isSecure : (window.location.protocol).toLowerCase().substr(0,5)==='https'
     Public = {};
     // get browser version
           tests.version = parseInt(/Firefox\/(\d+\.)/.exec(app)[1],10)
     }else if(isChrome){
           tests.version = parseInt(/Chrome\/(\d+\.)/.exec(app)[1],10)
     }else if(isSafari){
           tests.version = parseInt(/Version\/(\d+\.)/.exec(app)[1],10)
     }else if(isIE) {
           tests.version = parseInt(/MSIE (\d+\.)/.exec(app)[1],10)
     tests.mfCompliant = (isSafari && test.version>4) || (isIE && tests.version >8 && mode>8) || (isChrome && tests.version>20) || (isFireFox && tests.version>14);
     // convert results into anonymous function calls
     for(prop in tests){
           Public[prop]=new Function('return '+tests[prop]+';')
     return Public;                                    

Note that I am adding the mfCompliant property onto the tests object and setting my browser minimum requirements.  I am also not testing for Opera although that certainly could be added in very easily at any point in the future.  Finally I enumerate through the tests object and create anonymous functions within the Public object that return the values of the subsequent property in the tests object.  Note also the the public returned by the outer anonymous function is passed to the Object.freeze method in order to freeze the resulting object. This will prevent users from overriding existing methods or removing them.

In the case of IE9 it does not support the Object.freeze method.  As a result I had to place the following code above this module.

// Ensure we have freeze method on Object for IE9
if((typeof Object.freeze).toLowerCase()!=='function'){
       Object.prototype.freeze = function(o){
              return o

Sine the freeze method returns the object being frozen this little override does the same thing in order to ensure when running the framework in IE9 it does not blow up on you.  Freezing is certainly handy on objects but does not add any direct functionality to the framework.

The mf global variable browser is then returned as belonging as a child object to the framework.  This then allows external users to make calls such as mf.browser.isIE() or mf.browser.isSecure(). Certainly over time there may be other items to add under the browser module but these are the basics.

In my next post I will be fleshing out some other core methods for Objects, Arrays along with some base prototyping of core JavaScript objects such as String and Number.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s