/**
* Checks the current browser against a support map object.
*
+ * Version numbers passed as numeric values will be compared like numbers (1.2 > 1.11).
+ * Version numbers passed as string values will be compared using a simple component-wise
+ * algorithm, similar to PHP's version_compare ('1.2' < '1.11').
+ *
* A browser map is in the following format:
* {
* // Multiple rules with configurable operators
test: function ( map, profile, exactMatchOnly ) {
/*jshint evil: true */
- var conditions, dir, i, op, val;
+ var conditions, dir, i, op, val, j, pieceVersion, pieceVal, compare;
profile = $.isPlainObject( profile ) ? profile : $.client.profile();
if ( map.ltr && map.rtl ) {
dir = $( 'body' ).is( '.rtl' ) ? 'rtl' : 'ltr';
op = conditions[i][0];
val = conditions[i][1];
if ( typeof val === 'string' ) {
- if ( !( eval( 'profile.version' + op + '"' + val + '"' ) ) ) {
+ // Perform a component-wise comparison of versions, similar to PHP's version_compare
+ // but simpler. '1.11' is larger than '1.2'.
+ pieceVersion = profile.version.toString().split( '.' );
+ pieceVal = val.split( '.' );
+ // Extend with zeroes to equal length
+ while ( pieceVersion.length < pieceVal.length ) {
+ pieceVersion.push( '0' );
+ }
+ while ( pieceVal.length < pieceVersion.length ) {
+ pieceVal.push( '0' );
+ }
+ // Compare components
+ compare = 0;
+ for ( j = 0; j < pieceVersion.length; j++ ) {
+ if ( Number( pieceVersion[j] ) < Number( pieceVal[j] ) ) {
+ compare = -1;
+ break;
+ } else if ( Number( pieceVersion[j] ) > Number( pieceVal[j] ) ) {
+ compare = 1;
+ break;
+ }
+ }
+ // compare will be -1, 0 or 1, depending on comparison result
+ if ( !( eval( '' + compare + op + '0' ) ) ) {
return false;
}
} else if ( typeof val === 'number' ) {
rtl: true
}
},
- // Bug #34924
+ // Rekonq (bug 34924)
'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.34 (KHTML, like Gecko) rekonq Safari/534.34': {
title: 'Rekonq',
platform: 'Linux i686',
ltr: true,
rtl: true
}
+ },
+ // Konqueror
+ 'Mozilla/5.0 (X11; Linux i686) KHTML/4.9.1 (like Gecko) Konqueror/4.9': {
+ title: 'Konqueror',
+ platform: 'Linux i686',
+ profile: {
+ name: 'konqueror',
+ layout: 'khtml',
+ layoutVersion: 'unknown',
+ platform: 'linux',
+ version: '4.9.1',
+ versionBase: '4',
+ versionNumber: 4.9
+ },
+ wikiEditor: {
+ // '4.9' is less than '4.11'.
+ ltr: false,
+ rtl: false
+ },
+ wikiEditorLegacy: {
+ // The check is missing in legacyTestMap
+ ltr: true,
+ rtl: true
+ }
}
},
testMap = {
- // Example from WikiEditor
- // Make sure to use raw numbers, a string like "7.0" would fail on a
- // version 10 browser since in string comparaison "10" is before "7.0" :)
+ // Example from WikiEditor, modified to provide version identifiers as strings and with
+ // Konqueror 4.11 check added.
+ 'ltr': {
+ 'msie': [['>=', '7.0']],
+ 'firefox': [['>=', '2']],
+ 'opera': [['>=', '9.6']],
+ 'safari': [['>=', '3']],
+ 'chrome': [['>=', '3']],
+ 'netscape': [['>=', '9']],
+ 'konqueror': [['>=', '4.11']],
+ 'blackberry': false,
+ 'ipod': false,
+ 'iphone': false
+ },
+ 'rtl': {
+ 'msie': [['>=', '8']],
+ 'firefox': [['>=', '2']],
+ 'opera': [['>=', '9.6']],
+ 'safari': [['>=', '3']],
+ 'chrome': [['>=', '3']],
+ 'netscape': [['>=', '9']],
+ 'konqueror': [['>=', '4.11']],
+ 'blackberry': false,
+ 'ipod': false,
+ 'iphone': false
+ }
+ },
+ legacyTestMap = {
+ // Original example from WikiEditor.
+ // This is using the old, but still supported way of providing version identifiers as numbers
+ // instead of strings; with this method, 4.9 would be considered larger than 4.11.
'ltr': {
'msie': [['>=', 7.0]],
'firefox': [['>=', 2]],
}, ie7Profile, true ), false, 'returns false if browser not found and exactMatchOnly is set' );
} );
- QUnit.test( 'test( testMap) - WikiEditor sample', uacount * 2, function ( assert ) {
+ QUnit.test( 'test( testMap ), test( legacyTestMap ) - WikiEditor sample', uacount * 2 * 2, function ( assert ) {
var $body = $( 'body' ),
bodyClasses = $body.attr( 'class' );
// Loop through and run tests
$.each( uas, function ( agent, data ) {
$.each( ['ltr', 'rtl'], function ( i, dir ) {
- var profile, testMatch;
+ var profile, testMatch, legacyTestMatch;
$body.removeClass( 'ltr rtl' ).addClass( dir );
profile = $.client.profile( {
userAgent: agent,
platform: data.platform
} );
testMatch = $.client.test( testMap, profile );
+ legacyTestMatch = $.client.test( legacyTestMap, profile );
$body.removeClass( dir );
- assert.equal( testMatch, data.wikiEditor[dir], 'testing comparison based on ' + dir + ', ' + agent );
+ assert.equal(
+ testMatch,
+ data.wikiEditor[dir],
+ 'testing comparison based on ' + dir + ', ' + agent
+ );
+ assert.equal(
+ legacyTestMatch,
+ data.wikiEditorLegacy ? data.wikiEditorLegacy[dir] : data.wikiEditor[dir],
+ 'testing comparison based on ' + dir + ', ' + agent + ' (legacyTestMap)'
+ );
} );
} );