/* Private Members */
- var profile;
+ /**
+ * @var profileCache {Object} Keyed by userAgent string,
+ * value is the parsed $.client.profile object for that user agent.
+ */
+ var profileCache = {};
/* Public Methods */
$.client = {
/**
- * Returns an object containing information about the browser
+ * Get an object containing information about the client.
*
- * The resulting client object will be in the following format:
+ * @param nav {Object} An object with atleast a 'userAgent' and 'platform' key.=
+ * Defaults to the global Navigator object.
+ * @return {Object} The resulting client object will be in the following format:
* {
* 'name': 'firefox',
* 'layout': 'gecko',
* 'versionNumber': 3.5,
* }
*/
- profile: function() {
+ profile: function( nav ) {
+ if ( nav === undefined ) {
+ nav = window.navigator;
+ }
// Use the cached version if possible
- if ( profile === undefined ) {
+ if ( profileCache[nav.userAgent] === undefined ) {
/* Configuration */
/* Pre-processing */
- var userAgent = navigator.userAgent,
+ var ua = nav.userAgent,
match,
name = uk,
layout = uk,
platform = uk,
version = x;
- if ( match = new RegExp( '(' + wildUserAgents.join( '|' ) + ')' ).exec( userAgent ) ) {
+ if ( match = new RegExp( '(' + wildUserAgents.join( '|' ) + ')' ).exec( ua ) ) {
// Takes a userAgent string and translates given text into something we can more easily work with
- userAgent = translate( userAgent, userAgentTranslations );
+ ua = translate( ua, userAgentTranslations );
}
// Everything will be in lowercase from now on
- userAgent = userAgent.toLowerCase();
+ ua = ua.toLowerCase();
/* Extraction */
- if ( match = new RegExp( '(' + names.join( '|' ) + ')' ).exec( userAgent ) ) {
+ if ( match = new RegExp( '(' + names.join( '|' ) + ')' ).exec( ua ) ) {
name = translate( match[1], nameTranslations );
}
- if ( match = new RegExp( '(' + layouts.join( '|' ) + ')' ).exec( userAgent ) ) {
+ if ( match = new RegExp( '(' + layouts.join( '|' ) + ')' ).exec( ua ) ) {
layout = translate( match[1], layoutTranslations );
}
- if ( match = new RegExp( '(' + layoutVersions.join( '|' ) + ')\\\/(\\d+)').exec( navigator.userAgent.toLowerCase() ) ) {
+ if ( match = new RegExp( '(' + layoutVersions.join( '|' ) + ')\\\/(\\d+)').exec( ua ) ) {
layoutversion = parseInt( match[2], 10 );
}
- if ( match = new RegExp( '(' + platforms.join( '|' ) + ')' ).exec( navigator.platform.toLowerCase() ) ) {
+ if ( match = new RegExp( '(' + platforms.join( '|' ) + ')' ).exec( nav.platform.toLowerCase() ) ) {
platform = translate( match[1], platformTranslations );
}
- if ( match = new RegExp( '(' + versionPrefixes.join( '|' ) + ')' + versionSuffix ).exec( userAgent ) ) {
+ if ( match = new RegExp( '(' + versionPrefixes.join( '|' ) + ')' + versionSuffix ).exec( ua ) ) {
version = match[3];
}
}
// Expose Opera 10's lies about being Opera 9.8
if ( name === 'opera' && version >= 9.8) {
- version = userAgent.match( /version\/([0-9\.]*)/i )[1] || 10;
+ version = ua.match( /version\/([0-9\.]*)/i )[1] || 10;
}
var versionNumber = parseFloat( version, 10 ) || 0.0;
/* Caching */
- profile = {
+ profileCache[nav.userAgent] = {
'name': name,
'layout': layout,
'layoutVersion': layoutversion,
'versionNumber': versionNumber
};
}
- return profile;
+ return profileCache[nav.userAgent];
},
/**
* }
* }
*
- * @param map Object of browser support map
+ * @param map {Object} Browser support map
+ * @param profile {Object} (optional) a client-profile object.
*
* @return Boolean true if browser known or assumed to be supported, false if blacklisted
*/
- test: function( map ) {
- var profile = $.client.profile();
+ test: function( map, profile ) {
+ profile = $.isPlainObject( profile ) ? profile : $.client.profile();
+
var dir = $( 'body' ).is( '.rtl' ) ? 'rtl' : 'ltr';
// Check over each browser condition to determine if we are running in a compatible client
if ( typeof map[dir] !== 'object' || typeof map[dir][profile.name] === 'undefined' ) {
ok( jQuery.client, 'jQuery.client defined' );
});
-test( 'profile', function() {
+test( 'profile userAgent support', function() {
+ expect(8);
+
+ // Object keyed by userAgent. Value is an array (human-readable name, client-profile object, navigator.platform value)
+ // Info based on results from http://toolserver.org/~krinkle/testswarm/job/174/
+ var uas = {
+ // Internet Explorer 6
+ // Internet Explorer 7
+ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)': {
+ title: 'Internet Explorer 7',
+ platform: 'Win32',
+ profile: {
+ "name": "msie",
+ "layout": "trident",
+ "layoutVersion": "unknown",
+ "platform": "win",
+ "version": "7.0",
+ "versionBase": "7",
+ "versionNumber": 7
+ }
+ },
+ // Internet Explorer 8
+ // Internet Explorer 9
+ // Internet Explorer 10
+ // Firefox 2
+ // Firefox 3.5
+ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.19) Gecko/20110420 Firefox/3.5.19': {
+ title: 'Firefox 3.5',
+ platform: 'MacIntel',
+ profile: {
+ "name": "firefox",
+ "layout": "gecko",
+ "layoutVersion": 20110420,
+ "platform": "mac",
+ "version": "3.5.19",
+ "versionBase": "3",
+ "versionNumber": 3.5
+ }
+ },
+ // Firefox 3.6
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110422 Ubuntu/10.10 (maverick) Firefox/3.6.17': {
+ title: 'Firefox 3.6',
+ platform: 'Linux i686',
+ profile: {
+ "name": "firefox",
+ "layout": "gecko",
+ "layoutVersion": 20110422,
+ "platform": "linux",
+ "version": "3.6.17",
+ "versionBase": "3",
+ "versionNumber": 3.6
+ }
+ },
+ // Firefox 4
+ 'Mozilla/5.0 (Windows NT 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1': {
+ title: 'Firefox 4',
+ platform: 'Win32',
+ profile: {
+ "name": "firefox",
+ "layout": "gecko",
+ "layoutVersion": 20100101,
+ "platform": "win",
+ "version": "4.0.1",
+ "versionBase": "4",
+ "versionNumber": 4
+ }
+ },
+ // Firefox 5
+ // Safari 3
+ // Safari 4
+ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; nl-nl) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7': {
+ title: 'Safari 4',
+ platform: 'MacIntel',
+ profile: {
+ "name": "safari",
+ "layout": "webkit",
+ "layoutVersion": 531,
+ "platform": "mac",
+ "version": "4.0.5",
+ "versionBase": "4",
+ "versionNumber": 4
+ }
+ },
+ 'Mozilla/5.0 (Windows; U; Windows NT 6.0; cs-CZ) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7': {
+ title: 'Safari 4',
+ platform: 'Win32',
+ profile: {
+ "name": "safari",
+ "layout": "webkit",
+ "layoutVersion": 533,
+ "platform": "win",
+ "version": "4.0.5",
+ "versionBase": "4",
+ "versionNumber": 4
+ }
+ },
+ // Safari 5
+ // Opera 10
+ // Chrome 5
+ // Chrome 6
+ // Chrome 7
+ // Chrome 8
+ // Chrome 9
+ // Chrome 10
+ // Chrome 11
+ // Chrome 12
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.112 Safari/534.30': {
+ title: 'Chrome 12',
+ platform: 'MacIntel',
+ profile: {
+ "name": "chrome",
+ "layout": "webkit",
+ "layoutVersion": 534,
+ "platform": "mac",
+ "version": "12.0.742.112",
+ "versionBase": "12",
+ "versionNumber": 12
+ }
+ },
+ 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.68 Safari/534.30': {
+ title: 'Chrome 12',
+ platform: 'Linux i686',
+ profile: {
+ "name": "chrome",
+ "layout": "webkit",
+ "layoutVersion": 534,
+ "platform": "linux",
+ "version": "12.0.742.68",
+ "versionBase": "12",
+ "versionNumber": 12
+ }
+ }
+ };
+
+ // Generate a client profile object and compare recursively
+ var uaTest = function( rawUserAgent, data ) {
+ var ret = $.client.profile( {
+ userAgent: rawUserAgent,
+ platform: data.platform
+ } );
+ deepEqual( ret, data.profile, 'Client profile support check for ' + data.title + ' (' + data.platform + '): ' + rawUserAgent );
+ };
+
+ // Loop through and run tests
+ $.each( uas, uaTest );
+} );
+
+test( 'profile return validation for current user agent', function() {
expect(7);
var p = $.client.profile();
var unknownOrType = function( val, type, summary ) {