/** * This file contains code to handle determining the current browser. * It allows Javascript code to check if the current browser satisfies * a list of constraints which can include Browser name, operating system, and version. * The format is [browser name].[os name][op][version]. * where: op can be: ==, <, >, !=, <=, >= * To use simply pass an expression to coreweb.common.Browser.isBrowser(expression); * Some examples of expressions are: * Expression Description - isBrowser(expression) evaluates to true if... * .mac The user is running Mac * .linux The user is running Linux * .win The user is running Windows * ie.mac The user is running IE on Mac * !ie.mac The user is not running IE on Mac * safari.mac >= 1.2 The user is running Safari version 1.2 or higher on a Mac * safari < 1.2 * netscape.linux The user is running Netscape on Linux * netscape.windows * !netscape.windows The user is not running Nescape on Linux * ie.windows The user is running IE on Windows * * Or and And expressions are also supported (nested expressions are not yet supported): * ie.mac || safari < 1.2 || netscape < 7.2 * * The application server sets the current browser data in the 'questia.Dictionary.browser' * * @author Jeff Tassin */ questia.Package( "coreweb.common" ); __logger = function(msg) { // ignore for dv. } coreweb.common.BrowserTag = function() { this.browser = null; this.op = null; this.version = null; this.os = null; this.negate = null; this.toString=function(){ var result = "BrowserTag-browser: "+this.browser+", op: " + this.op + ", version = " + this.version + ", os: " + this.os + ", negate: " + this.negate; return result; } this.evaluate = function( browserProps ) { var result = this._evaluate(browserProps); if (this.negate) return !result; else return result; } this._evaluate = function( browserProps ) { if ( !browserProps ) throw "BrowserTag.evaluate browserProps == null"; if ("*" == this.browser) { return true; } /** check that the browser names are the same */ if (!this.compare(this.browser, browserProps.browser)) { return false; } var sos = this.os != null ? this.os.toLowerCase() : ""; sos = sos == 'microsoft' ? 'windows' : sos; var sbos = browserProps.os != null ? browserProps.os.toLowerCase() : ""; sbos = sbos == 'microsoft' ? 'windows' : sbos; if (!this.compare( sos, sbos )) { return false; } if (this.op == null || this.op.length == 0 ) { return true; } // current supported operators: <, >, =, <=, >=, !=, ==, var bversion = browserProps.version; if (this.op.length == 1) { var c1 = this.op.charAt(0); switch (c1) { case '>': return bversion > this.version; case '<': return bversion < this.version; case '=': return bversion == this.version; default: throw "Invalid operator: " + this.browser + this.op + this.version; } } else if (this.op.length == 2) { var c1 = this.op.charAt(0); var c2 = this.op.charAt(1); switch (c1) { case '>': if (c2 == '=') { return bversion >= this.version; } case '<': if (c2 == '=') return bversion <= this.version; case '=': if (c2 == '=') return bversion == this.version; case '!': if (c2 == '=') return bversion != this.version; } throw "Invalid operator: " + this.browser + this.op + this.version; } else { throw "Invalid operator: " + this.browser + this.op + this.version; } } this.compare = function(tagValue, val2) { if (tagValue == null || tagValue.length == 0) { return true; } else if ( val2 == null ) { return false; } else { tagValue = coreweb.common.trim(tagValue); val2 = coreweb.common.trim(val2); return tagValue.toLowerCase() == val2.toLowerCase(); } } } coreweb.common.BrowserTag.create = function(browser,op,version ) { this.convertName = function(browserName) { browserName = browserName.toLowerCase(); if ("mac" == browserName) { return "Macintosh"; } else if ("win" == browserName || "windows" == browserName ) { return "Microsoft"; } else { return browserName; } } var tag = new coreweb.common.BrowserTag(); var negate = false; var c1 = browser.charAt(0); if (c1 == '!') { negate = true; browser = browser.substring(1,browser.length - 1); tag.negate = true; } var ppos = browser.indexOf('.'); if (ppos >= 0) { tag.browser = browser.substring(0, ppos); tag.os = this.convertName(browser.substring(ppos + 1, browser.length)); } else { tag.browser = browser; } tag.op = op; tag.version = version; if (op != null && negate) { throw "BrowserTag invalid. ! and operators cannot be used together: " + browser + op + version; } return tag; } coreweb.common.Browser = {}; coreweb.common.Browser.isBrowser = function( exprList ) { var _expressions = []; this.addTag = function( bTag, logical ) { __logger( "addTag: " + bTag.browser + " logical: " + logical ); if( bTag ) { _expressions.push( bTag ); if ( logical ) _expressions.push( logical ); } } this.evaluateRule = function(expr) { var pattern = /([!]?[a-zA-Z]+([\.][a-zA-Z]+)?\s*)((>=|<=|<|>|==|=|!=)(\s*[0-9]+(\.[0-9]+)?))?/; var result = expr.match(pattern); if ( result != null ) { var vos = result[1]; var vop = result[4]; var vversion= result[5]; var browserTag = { browser: vos, op: vop, version: vversion }; __logger( "browser matched... " + browserTag.browser + " op: " + browserTag.op + " version: " + browserTag.version ); return browserTag; } } this.evaluate = function(exprList) { var last=0; var pattern = /&&|\|\|/g; while((match = pattern.exec( exprList )) != null) { var expr = exprList.substring(last, match.index); var logical = exprList.substring(match.index,match.index+2); last = pattern.lastIndex; this.addTag(this.evaluateRule( expr ), logical ); } if ( last == 0 ) { this.addTag(this.evaluateRule(exprList)); } else { var expr = exprList.substring(last, exprList.length ); this.addTag(this.evaluateRule( expr )); } } this.evaluate(exprList); var lastlogical; var lastresult = true; for( var i=0; i < _expressions.length; i++ ) { var expr = _expressions[i]; __logger( "expr: " + expr + " at i=" + i ); } for( var i=0; i < _expressions.length; i++ ) { var expr = _expressions[i]; var btag = new coreweb.common.BrowserTag.create( expr.browser, expr.op, expr.version ); __logger( btag.toString() ); var result = btag.evaluate( questia.Dictionary.browser ); if ( lastlogical != null ) { if ( lastlogical == '||' && (result || lastresult)) return true; else if ( lastlogical == '&&' && !(result && lastresult) ) return false; } lastresult = result; if ( (i+1) < _expressions.length ) { i++; lastlogical = _expressions[i]; if ( lastlogical != '&&' && lastlogical != '||') throw "Logical operand expected at index i=" + i + " " + lastlogical; } } return lastresult; } coreweb.common.Browser.isIE6 = function( exprList ) { return coreweb.common.Browser.isBrowser("ie.windows < 7"); } //questia.Dictionary.browser = {browser: 'Firefox', version: 1.2, os: 'Linux'}; //evalBrowser = [{browser: 'Firefox', version: 1.0, op: '<=', os: 'Linux'}, "||", {browser: 'ie', os: 'mac' }] //evalBrowser = {browser: 'Firefox', version: 1.0, op: '<=', os: 'Linux'}; //evalBrowser = "FireFox < 1.2 || ie.mac"; //evalBrowser = "ie.mac || Firefox"; //__logger( "evalbrowser: " + coreweb.common.Browser.isBrowser( evalBrowser ) );