Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4106410
jquery.client.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
jquery.client.js
View Options
/*!
* jQuery Client 3.0.0
* https://gerrit.wikimedia.org/g/jquery-client/
*
* Copyright 2010-2020 wikimedia/jquery-client maintainers and other contributors.
* Released under the MIT license
* https://jquery-client.mit-license.org
*/
/**
* User-agent detection
*
* @class jQuery.client
* @singleton
*/
(
function
()
{
/**
* @private
* @property {Object} profileCache Keyed by userAgent string,
* value is the parsed $.client.profile object for that user agent.
*/
var
profileCache
=
{};
$
.
client
=
{
/**
* Get an object containing information about the client.
*
* The resulting client object will be in the following format:
*
* {
* 'name': 'firefox',
* 'layout': 'gecko',
* 'layoutVersion': 20101026,
* 'platform': 'linux'
* 'version': '3.5.1',
* 'versionBase': '3',
* 'versionNumber': 3.5,
* }
*
* Example:
*
* if ( $.client.profile().layout == 'gecko' ) {
* // This will only run in Gecko browsers, such as Mozilla Firefox.
* }
*
* var profile = $.client.profile();
* if ( profile.layout == 'gecko' && profile.platform == 'linux' ) {
* // This will only run in Gecko browsers on Linux.
* }
*
* Recognised browser names:
*
* - `android` (legacy Android browser, prior to Chrome Mobile)
* - `chrome` (includes Chrome Mobile, Microsoft Edge, Opera, and others)
* - `crios` (Chrome on iOS, which uses Mobile Safari)
* - `edge` (legacy Microsoft Edge, which uses EdgeHTML)
* - `firefox` (includes Firefox Mobile, Iceweasel, and others)
* - `fxios` (Firefox on iOS, which uses Mobile Safari)
* - `konqueror`
* - `msie`
* - `opera` (legacy Opera, which uses Presto)
* - `rekonq`
* - `safari` (including Mobile Safari)
* - `silk`
*
* Recognised layout engines:
*
* - `edge` (EdgeHTML 12-18, as used by legacy Microsoft Edge)
* - `gecko`
* - `khtml`
* - `presto`
* - `trident`
* - `webkit`
*
* Note that Chrome and Chromium-based browsers like Opera have their layout
* engine identified as `webkit`.
*
* Recognised platforms:
*
* - `ipad`
* - `iphone`
* - `linux`
* - `mac`
* - `solaris` (untested)
* - `win`
*
* @param {Object} [nav] An object with a 'userAgent' and 'platform' property.
* Defaults to the global `navigator` object.
* @return {Object} The client object
*/
profile
:
function
(
nav
)
{
if
(
!
nav
)
{
nav
=
window
.
navigator
;
}
// Use the cached version if possible
if
(
profileCache
[
nav
.
userAgent
+
'|'
+
nav
.
platform
]
)
{
return
profileCache
[
nav
.
userAgent
+
'|'
+
nav
.
platform
];
}
// eslint-disable-next-line vars-on-top
var
versionNumber
,
key
=
nav
.
userAgent
+
'|'
+
nav
.
platform
,
// Configuration
// Name of browsers or layout engines we don't recognize
uk
=
'unknown'
,
// Generic version digit
x
=
'x'
,
// Fixups for user agent strings that contain wild words
wildFixups
=
[
// Chrome lives in the shadow of Safari still
[
'Chrome Safari'
,
'Chrome'
],
// KHTML is the layout engine not the browser - LIES!
[
'KHTML/'
,
'Konqueror/'
],
// For Firefox Mobile, strip out "Android;" or "Android [version]" so that we
// classify it as Firefox instead of Android (default browser)
[
/Android(?:;|\s[a-zA-Z0-9.+-]+)(.*Firefox)/
,
'$1'
]
],
// Strings which precede a version number in a user agent string
versionPrefixes
=
'(?:chrome|crios|firefox|fxios|opera|version|konqueror|msie|safari|android)'
,
// This matches the actual version number, with non-capturing groups for the
// separator and suffix
versionSuffix
=
'(?:\\/|;?\\s|)([a-z0-9\\.\\+]*?)(?:;|dev|rel|\\)|\\s|$)'
,
// Match the names of known browser families
rName
=
/(chrome|crios|firefox|fxios|konqueror|msie|opera|safari|rekonq|android)/
,
// Match the name of known layout engines
rLayout
=
/(gecko|konqueror|msie|trident|edge|opera|webkit)/
,
// Translations for conforming layout names
layoutMap
=
{
konqueror
:
'khtml'
,
msie
:
'trident'
,
opera
:
'presto'
},
// Match the prefix and version of supported layout engines
rLayoutVersion
=
/(applewebkit|gecko|trident|edge)\/(\d+)/
,
// Match the name of known operating systems
rPlatform
=
/(win|wow64|mac|linux|sunos|solaris|iphone|ipad)/
,
// Translations for conforming operating system names
platformMap
=
{
sunos
:
'solaris'
,
wow64
:
'win'
},
// Pre-processing
ua
=
nav
.
userAgent
,
match
,
name
=
uk
,
layout
=
uk
,
layoutversion
=
uk
,
platform
=
uk
,
version
=
x
;
// Takes a userAgent string and fixes it into something we can more
// easily work with
wildFixups
.
forEach
(
function
(
fixup
)
{
ua
=
ua
.
replace
(
fixup
[
0
],
fixup
[
1
]
);
}
);
// Everything will be in lowercase from now on
ua
=
ua
.
toLowerCase
();
// Extraction
if
(
(
match
=
rName
.
exec
(
ua
)
)
)
{
name
=
match
[
1
];
}
if
(
(
match
=
rLayout
.
exec
(
ua
)
)
)
{
layout
=
layoutMap
[
match
[
1
]
]
||
match
[
1
];
}
if
(
(
match
=
rLayoutVersion
.
exec
(
ua
)
)
)
{
layoutversion
=
parseInt
(
match
[
2
],
10
);
}
if
(
(
match
=
rPlatform
.
exec
(
nav
.
platform
.
toLowerCase
()
)
)
)
{
platform
=
platformMap
[
match
[
1
]
]
||
match
[
1
];
}
if
(
(
match
=
new
RegExp
(
versionPrefixes
+
versionSuffix
).
exec
(
ua
)
)
)
{
version
=
match
[
1
];
}
// Edge Cases -- did I mention about how user agent string lie?
// Decode Safari's crazy 400+ version numbers
if
(
name
===
'safari'
&&
version
>
400
)
{
version
=
'2.0'
;
}
// Expose Opera 10's lies about being Opera 9.8
if
(
name
===
'opera'
&&
version
>=
9.8
)
{
match
=
ua
.
match
(
/\bversion\/([0-9.]*)/
);
if
(
match
&&
match
[
1
]
)
{
version
=
match
[
1
];
}
else
{
version
=
'10'
;
}
}
// And IE 11's lies about being not being IE
if
(
layout
===
'trident'
&&
layoutversion
>=
7
&&
(
match
=
ua
.
match
(
/\brv[ :/]([0-9.]*)/
)
)
)
{
if
(
match
[
1
]
)
{
name
=
'msie'
;
version
=
match
[
1
];
}
}
// And MS Edge's lies about being Chrome
//
// It's different enough from classic IE Trident engine that they do this
// to avoid getting caught by MSIE-specific browser sniffing.
if
(
name
===
'chrome'
&&
(
match
=
ua
.
match
(
/\bedge\/([0-9.]*)/
)
)
)
{
name
=
'edge'
;
version
=
match
[
1
];
layout
=
'edge'
;
layoutversion
=
parseInt
(
match
[
1
],
10
);
}
// And Amazon Silk's lies about being Android on mobile or Safari on desktop
if
(
(
match
=
ua
.
match
(
/\bsilk\/([0-9.\-_]*)/
)
)
)
{
if
(
match
[
1
]
)
{
name
=
'silk'
;
version
=
match
[
1
];
}
}
versionNumber
=
parseFloat
(
version
,
10
)
||
0.0
;
// Caching
profileCache
[
key
]
=
{
name
:
name
,
layout
:
layout
,
layoutVersion
:
layoutversion
,
platform
:
platform
,
version
:
version
,
versionBase
:
(
version
!==
x
?
Math
.
floor
(
versionNumber
).
toString
()
:
x
),
versionNumber
:
versionNumber
};
return
profileCache
[
key
];
},
/**
* 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
* 'msie': [['>=', 7], ['!=', 9]],
* // Match no versions
* 'iphone': false,
* // Match any version
* 'android': null
* }
*
* It can optionally be split into ltr/rtl sections:
*
* {
* 'ltr': {
* 'android': null,
* 'iphone': false
* },
* 'rtl': {
* 'android': false,
* // rules are not inherited from ltr
* 'iphone': false
* }
* }
*
* @param {Object} map Browser support map
* @param {Object} [profile] A client-profile object
* @param {boolean} [exactMatchOnly=false] Only return true if the browser is matched,
* otherwise returns true if the browser is not found.
*
* @return {boolean} The current browser is in the support map
*/
test
:
function
(
map
,
profile
,
exactMatchOnly
)
{
var
conditions
,
dir
,
i
,
op
,
val
,
j
,
pieceVersion
,
pieceVal
,
compare
;
profile
=
$
.
isPlainObject
(
profile
)
?
profile
:
$
.
client
.
profile
();
if
(
map
.
ltr
&&
map
.
rtl
)
{
dir
=
$
(
document
.
body
).
is
(
'.rtl'
)
?
'rtl'
:
'ltr'
;
map
=
map
[
dir
];
}
// Check over each browser condition to determine if we are running in a
// compatible client
if
(
typeof
map
!==
'object'
||
map
[
profile
.
name
]
===
undefined
)
{
// Not found, return true if exactMatchOnly not set, false otherwise
return
!
exactMatchOnly
;
}
conditions
=
map
[
profile
.
name
];
if
(
conditions
===
false
)
{
// Match no versions
return
false
;
}
if
(
conditions
===
null
)
{
// Match all versions
return
true
;
}
for
(
i
=
0
;
i
<
conditions
.
length
;
i
++
)
{
op
=
conditions
[
i
][
0
];
val
=
conditions
[
i
][
1
];
if
(
typeof
val
===
'string'
)
{
// 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
// eslint-disable-next-line no-eval
if
(
!
(
eval
(
String
(
compare
+
op
+
'0'
)
)
)
)
{
return
false
;
}
}
else
if
(
typeof
val
===
'number'
)
{
// eslint-disable-next-line no-eval
if
(
!
(
eval
(
'profile.versionNumber'
+
op
+
val
)
)
)
{
return
false
;
}
}
}
return
true
;
}
};
}()
);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Aug 18, 19:31 (2 w, 4 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
49/32/3e24a718dc29c9e1473ad3a5f7ef
Default Alt Text
jquery.client.js (10 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment