I have the following in "home.html":

<html>
  <head>
    <script type="text/javascript" src="sandbox.js"></script>
  </head>
  <body onload="compatibilityCheck();">
  <div id="content">
      <p>You need to enable JavaScript to use this site</p>
  </div>
.....

where "sandbox.js" is:

function compatibilityCheck() {
  var compatibilityCheck = new compatibilityCheck;
  compatibilityCheck.browser;
  compatibilityCheck.cookies;
}

var compatibilityCheck {
  browser : function() { 
    switch(navigator.appName) {
      case 'Microsoft Internet Explorer':
        if (!navigator.appVersion >= 7) {
          document.getElementById("content").innerHTML = "<p>You need IE 7 or 8 to use this site</p>";  
        };
        break;
      case 'Firefox':
      case 'Chrome':
      case 'Safari':
      case 'Opera':
        return(document.getElementById("content").innerHTML = "<p>You are using"+navigator.appName"</p>");
        break;
      default:
        return(document.getElementById("content").innerHTML = "<p>Please use IE 7, Firefox, Chrome, Safari or Opera</p>");  
    }
  },
  cookies : function() {
    var tempCookie = new Date();
    checkCookie = (tempCookie.getTime() + '');
    document.cookie = "checkCookie=" + checkCookie + "; path=/";
    if (document.cookie.indexOf(checkCookie,0) < 0) {
      return(document.getElementById('content').innerHTML = "<p>You need to enable Cookies to use this site</p>");
    }
  }
}

Now I am using Opera 10 and when I loaded "home.html" (it is stored on http://localhost.localdomain) I expected it to change "content" to "You are usingOpera"...but it didn't :(. (I have JS and Cookies enabled)

This is my first attempt at OO JS/JSON and would really appreciate it if a more experience programmer could point out where I've gone wrong. Thanks in advance for any help/tips/pointers :)

Recommended Answers

All 4 Replies

JRW,

In javascript function x(){...} and var x = function(){...} do exactly the same thing - namely define a function named x. From this, you will see that your second use of "compatibilityCheck" overwrites the first (without throwig an error).

Your code makes a good a attempt at defining a javascsript namespace, a slightly tricky beast normally written in the form of a self-executing function. In essence the namespace pattern is:

var X = function(){//NAMESPACE pattern
  var private_a=...;
  var private_b=...;
  return{
    privileged_a:...,
    privileged_b:...
  };
}();

Note the () at the end, which causes the function to execute immediately, returning an object to the variable X. What is not immeiately obvious is how the private members remain alive. This is achieved by a feature of javascript called "closure" (further reading recommended). The scopes of the various members in a namespace are summariased as follows:

  • Private members can be seen only by each other and Privileged members.
  • Privileged members are Public and can be seen only from outside the namespace and from any member within the namespace by addressing as if they were in another namespace, eg. X.privileged_a . Privileged members cannot see each other directly.
  • After a namespace has been defined, only non-Privileged, Public members can be added. eg. X.public_a = ....; . Such members cannot see Private members (because they are not Privileged).
  • Global members can be seen by all namespace members.

Your checks can be framed in many different ways. Here is one, which defines a UTILITIES namespace (by convention we use ALL_CAPS for namespaces and Initial_Caps for constructors) containing only Privileged members.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<style>
#browserMessage { padding:0 6px; background-color:#e0f0f0; }
#cookieMessage  { padding:0 6px; background-color:#e0f0f0; }
</style>
<script>
var UTILITIES = function(containerID){//NAMESPACE pattern
  // Private members
  // none  

  // Privileged members
  return{
    Cookie : function( path, domain, secure ){//Contructor
      this.path   = (!path)   ? null : path;
      this.domain = (!domain) ? null : domain;
      this.secure = (!secure) ? null : secure;
      this.save = function(expires){
        var today = new Date();
        today.setTime( today.getTime() );
        expires = (expires) ? expires * 1000 * 60 * 60 * 24 : 0;//value in days.
        this.expires_date = new Date( today.getTime() + expires );
        var valArray = [];
        for(prop in this){
          if(typeof this[prop] !== 'function' && this[prop] !== null){
            valArray.push( [prop, escape(this[prop])].join('=') );
          }
        }
        document.cookie = valArray.join(';');
      };
      this.set = function(name, value){
        if(!name)  { return; }
        value = (!value) ? '' : value;
        this[name] = value;
      };
      this.get = function(){
        var pairs = document.cookie.split( ';' );
        for(var i=0; i<pairs.length; i++){
          var pair = pairs[i].split('=');
          if(pair.length == 2){
            this[pair[0].replace(/^\s+|\s+$/g, '')] = unescape(pair[1].replace(/^\s+|\s+$/g, ''));
          }
        }
      };
    },
    browserCompatibilityCheck : function(containerID){
      var msg = "Browser version is OK";
      var el = document.getElementById(containerID);
      switch(navigator.appName){
        case 'Microsoft Internet Explorer':
          if(navigator.appVersion < 7) { msg = "You need IE 7 or 8 to use this site."; }
          break;
        case 'Firefox':
        case 'Chrome':
        case 'Safari':
        case 'Opera':
          msg = "You are using" + navigator.appName;
          break;
        default:
          msg = "Please use IE 7, Firefox, Chrome, Safari or Opera";
      }
      (!el) ? alert(msg) : (el.innerHTML = msg);
    },
    cookieCheck : function(containerID){
      var msg = 'Cookies - OK';
      var el = document.getElementById(containerID);
      var cookie = new UTILITIES.Cookie();
      var now = new Date();
      cookie.set( 'checkVal', now.getTime() );
      cookie.save(1/24/60);
      if ( cookie.checkVal !== now.getTime() ) {
        msg = "You need to enable Cookies to use this site";
      }
      (!el) ? alert(msg) : (el.innerHTML = msg);
    }
  };
}();

onload = function(){
  UTILITIES.browserCompatibilityCheck('browserMessage');
  UTILITIES.cookieCheck('cookieMessage');
};

</script>
</head>
<html>

This probably asks as many questions as it answers but should give you enough clues for you to start your own reading. The internet abounds with good advice on javascript basics and advanced techniques. Read everything you can by Douglas Crockford.

Airshow

I realize your question is about object creation and use, about which I know little, but permit me to add an FYI about navigator.appName:

When I tested Airshow's code in my browser (Chrome) I noticed that the property you are testing, navigator.appName returns 'Netscape' when run in Chrome. I don't know why, but googled it and found that navigator.appName returns 'Netscape' in Safari and Firefox as well (see http://code.google.com/p/doctype/wiki/NavigatorAppNameProperty). You will have to test some property other than navigator.appName to detect browsers other than Microsoft Internet Explorer and Opera.

D5E5 is right, navigator.appName is not the best way to test which browser is in use. I didn't alter this aspect of the code, just got the original working without changing the test logic.

For more discriminating tests, try sticking "javascript browser sniffer" into Google - you should get plenty of good suggstions.

But please note that browser sniffing (of this type) is not generally recommeneded for cross-browser script compatibility. There are much better ways (eg, try/catch, or test function/property exists before use). These will make the code more reliable and more future proof. And that's why I'm not an expert on navigator.appName - haven't used it for years.

Airshow

D5E5 is right, navigator.appName is not the best way to test which browser is in use. I didn't alter this aspect of the code, just got the original working without changing the test logic.

For more discriminating tests, try sticking "javascript browser sniffer" into Google - you should get plenty of good suggstions.

But please note that browser sniffing (of this type) is not generally recommeneded for cross-browser script compatibility. There are much better ways (eg, try/catch, or test function/property exists before use). These will make the code more reliable and more future proof. And that's why I'm not an expert on navigator.appName - haven't used it for years.

Airshow

Thanks for the help, it now works!!!! :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.