Comparing version 0.3.1 to 0.4.0
@@ -17,2 +17,3 @@ # Platform.js API documentation | ||
* [`platform.product`](#platform.product) | ||
* [`platform.ua`](#platform.ua) | ||
* [`platform.version`](#platform.version) | ||
@@ -38,3 +39,3 @@ * [`platform.noConflict`](#platform.noConflict) | ||
### <a id="platform" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L766" title="View in source">`platform`</a> | ||
### <a id="platform" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L784" title="View in source">`platform`</a> | ||
*(Object)*: The platform object. | ||
@@ -48,4 +49,4 @@ [▲][1] | ||
### <a id="platform.description" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L796" title="View in source">`platform.description`</a> | ||
*(String)*: The platform description. | ||
### <a id="platform.description" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L814" title="View in source">`platform.description`</a> | ||
*(String, Null)*: The platform description. | ||
[▲][1] | ||
@@ -58,3 +59,3 @@ | ||
### <a id="platform.layout" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L803" title="View in source">`platform.layout`</a> | ||
### <a id="platform.layout" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L821" title="View in source">`platform.layout`</a> | ||
*(String, Null)*: The name of the browser layout engine. | ||
@@ -68,3 +69,3 @@ [▲][1] | ||
### <a id="platform.manufacturer" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L810" title="View in source">`platform.manufacturer`</a> | ||
### <a id="platform.manufacturer" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L828" title="View in source">`platform.manufacturer`</a> | ||
*(String, Null)*: The name of the product's manufacturer. | ||
@@ -78,3 +79,3 @@ [▲][1] | ||
### <a id="platform.name" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L780" title="View in source">`platform.name`</a> | ||
### <a id="platform.name" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L798" title="View in source">`platform.name`</a> | ||
*(String, Null)*: The name of the browser/environment. | ||
@@ -88,3 +89,3 @@ [▲][1] | ||
### <a id="platform.os" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L787" title="View in source">`platform.os`</a> | ||
### <a id="platform.os" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L805" title="View in source">`platform.os`</a> | ||
*(String, Null)*: The name of the operating system. | ||
@@ -98,3 +99,3 @@ [▲][1] | ||
### <a id="platform.prerelease" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L817" title="View in source">`platform.prerelease`</a> | ||
### <a id="platform.prerelease" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L835" title="View in source">`platform.prerelease`</a> | ||
*(String, Null)*: The alpha/beta release indicator. | ||
@@ -108,3 +109,3 @@ [▲][1] | ||
### <a id="platform.product" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L824" title="View in source">`platform.product`</a> | ||
### <a id="platform.product" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L842" title="View in source">`platform.product`</a> | ||
*(String, Null)*: The name of the product hosting the browser. | ||
@@ -118,3 +119,12 @@ [▲][1] | ||
### <a id="platform.version" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L773" title="View in source">`platform.version`</a> | ||
### <a id="platform.ua" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L849" title="View in source">`platform.ua`</a> | ||
*(String, Null)*: The browser's user agent string. | ||
[▲][1] | ||
<!-- /div --> | ||
<!-- div --> | ||
### <a id="platform.version" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L791" title="View in source">`platform.version`</a> | ||
*(String, Null)*: The browser/environment version. | ||
@@ -128,3 +138,3 @@ [▲][1] | ||
### <a id="platform.noConflict" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L506" title="View in source">`platform.noConflict()`</a> | ||
### <a id="platform.noConflict" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L492" title="View in source">`platform.noConflict()`</a> | ||
Restores a previously overwritten platform object. | ||
@@ -141,3 +151,3 @@ [▲][1] | ||
### <a id="platform.parse" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L225" title="View in source">`platform.parse([ua = navigator.userAgent])`</a> | ||
### <a id="platform.parse" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L219" title="View in source">`platform.parse([ua = navigator.userAgent])`</a> | ||
Creates a new platform object. | ||
@@ -157,3 +167,3 @@ [▲][1] | ||
### <a id="platform.toString" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L518" title="View in source">`platform.toString()`</a> | ||
### <a id="platform.toString" href="https://github.com/bestiejs/platform.js/blob/master/platform.js#L504" title="View in source">`platform.toString()`</a> | ||
Return platform description when the platform object is coerced to a string. | ||
@@ -160,0 +170,0 @@ [▲][1] |
{ | ||
"name": "platform", | ||
"version": "0.3.1", | ||
"version": "0.4.0", | ||
"description": "A platform detection library that works on nearly all JavaScript platforms.", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/bestiejs/platform.js", |
267
platform.js
@@ -20,2 +20,5 @@ /*! | ||
/** Used to check for own properties of an object */ | ||
hasOwnProperty = {}.hasOwnProperty, | ||
/** Used to resolve a value's internal [[Class]] */ | ||
@@ -36,5 +39,2 @@ toString = {}.toString, | ||
/** Used to preserve a pristine reference */ | ||
hasOwnProperty = {}.hasOwnProperty, | ||
/** Browser navigator object */ | ||
@@ -47,3 +47,3 @@ nav = window.navigator || {}, | ||
/** Browser user agent string */ | ||
userAgent = nav.userAgent || 'unknown platform', | ||
userAgent = nav.userAgent || '', | ||
@@ -77,18 +77,6 @@ /** | ||
/** | ||
* Camel cases a spaced separated string. | ||
* @private | ||
* @param {String} string The string to camel case. | ||
* @returns {String} The camel casesed string. | ||
*/ | ||
function camelCase(string) { | ||
return String(string).replace(/([a-z\d]) +([a-z])/ig, '$1$2'); | ||
} | ||
/** | ||
* An iteration utility for arrays and objects. | ||
* Callbacks may terminate the loop by explicitly returning `false`. | ||
* @private | ||
* @param {Array|Object} object The object to iterate over. | ||
* @param {Function} callback The function called per iteration. | ||
* @returns {Array|Object} Returns the object iterated over. | ||
*/ | ||
@@ -101,10 +89,7 @@ function each(object, callback) { | ||
while (++index < length) { | ||
if (callback(object[index], index, object) === false) { | ||
break; | ||
} | ||
callback(object[index], index, object); | ||
} | ||
} else { | ||
forIn(object, callback); | ||
forOwn(object, callback); | ||
} | ||
return object; | ||
} | ||
@@ -117,12 +102,7 @@ | ||
* @param {Function} callback The function executed per own property. | ||
* @returns {Object} Returns the object iterated over. | ||
*/ | ||
function forIn(object, callback) { | ||
function forOwn(object, callback) { | ||
for (var key in object) { | ||
if (hasKey(object, key) && | ||
callback(object[key], key, object) === false) { | ||
break; | ||
} | ||
hasKey(object, key) && callback(object[key], key, object); | ||
} | ||
return object; | ||
} | ||
@@ -162,20 +142,24 @@ | ||
*/ | ||
function hasKey(object, key) { | ||
var result, | ||
parent = (object.constructor || Object).prototype; | ||
function hasKey() { | ||
// lazy define for others (not as accurate) | ||
hasKey = function(object, key) { | ||
var parent = (object.constructor || Object).prototype; | ||
return key in Object(object) && !(key in parent && object[key] === parent[key]); | ||
}; | ||
// for modern browsers | ||
object = Object(object); | ||
if (getClassOf(hasOwnProperty) == 'Function') { | ||
result = hasOwnProperty.call(object, key); | ||
hasKey = function(object, key) { | ||
return hasOwnProperty.call(object, key); | ||
}; | ||
} | ||
// for Safari 2 | ||
else if ({}.__proto__ == Object.prototype) { | ||
object.__proto__ = [object.__proto__, object.__proto__ = null, result = key in object][0]; | ||
hasKey = function(object, key) { | ||
var result; | ||
object = Object(object); | ||
object.__proto__ = [object.__proto__, object.__proto__ = null, result = key in object][0]; | ||
return result; | ||
}; | ||
} | ||
// for others (not as accurate) | ||
else { | ||
result = key in object && !(key in parent && object[key] === parent[key]); | ||
} | ||
return result; | ||
return hasKey.apply(this, arguments); | ||
} | ||
@@ -215,2 +199,12 @@ | ||
/** | ||
* Prepares a string for use in a RegExp constructor by making hyphens and spaces optional. | ||
* @private | ||
* @param {String} string The string to qualify. | ||
* @returns {String} The qualified string. | ||
*/ | ||
function qualify(string) { | ||
return String(string).replace(/([ -])(?!$)/g, '$1?'); | ||
} | ||
/** | ||
* Removes leading and trailing whitespace from a string. | ||
@@ -238,3 +232,3 @@ * @private | ||
/** Temporary variable used over the script's lifetime */ | ||
var data = {}, | ||
var data, | ||
@@ -255,3 +249,3 @@ /** Platform description array */ | ||
layout = getLayout([ | ||
'WebKit', | ||
{ 'label': 'WebKit', 'pattern': 'AppleWebKit' }, | ||
'iCab', | ||
@@ -268,2 +262,3 @@ 'Presto', | ||
name = getName([ | ||
'Adobe AIR', | ||
'Arora', | ||
@@ -285,2 +280,3 @@ 'Avant Browser', | ||
'Nook Browser', | ||
'PhantomJS', | ||
'Raven', | ||
@@ -290,3 +286,3 @@ 'Rekonq', | ||
'SeaMonkey', | ||
'Silk', | ||
{ 'label': 'Silk', 'pattern': '(?:Cloud9|Silk)' }, | ||
'Sleipnir', | ||
@@ -296,7 +292,8 @@ 'SlimBrowser', | ||
'Swiftfox', | ||
'WebPositive', | ||
'Opera Mini', | ||
'Opera', | ||
'Chrome', | ||
'Firefox', | ||
'IE', | ||
{ 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' }, | ||
{ 'label': 'IE', 'pattern': 'MSIE' }, | ||
'Safari' | ||
@@ -308,4 +305,4 @@ ]), | ||
'BlackBerry', | ||
'Galaxy S', | ||
'Galaxy S2', | ||
{ 'label': 'Galaxy S', 'pattern': 'GT-I9000' }, | ||
{ 'label': 'Galaxy S2', 'pattern': 'GT-I9100' }, | ||
'iPad', | ||
@@ -315,3 +312,3 @@ 'iPod', | ||
'Kindle', | ||
'Kindle Fire', | ||
{ 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk)' }, | ||
'Nook', | ||
@@ -346,2 +343,3 @@ 'PlayBook', | ||
'Gentoo', | ||
'Haiku', | ||
'Kubuntu', | ||
@@ -377,4 +375,5 @@ 'Linux Mint', | ||
return reduce(guesses, function(result, guess) { | ||
return result || RegExp('\\b' + | ||
(guess == 'WebKit' ? 'AppleWebKit' : guess) + '\\b', 'i').exec(ua) && guess; | ||
return result || RegExp('\\b' + ( | ||
guess.pattern || qualify(guess) | ||
) + '\\b', 'i').exec(ua) && (guess.label || guess); | ||
}); | ||
@@ -392,9 +391,7 @@ } | ||
// lookup the manufacturer by product or scan the UA for the manufacturer | ||
return result || reduce([key, camelCase(key)], function(result, key) { | ||
return result || ( | ||
value[product] || | ||
value[0/*Opera 9.25 fix*/, /^[a-z]+/i.exec(product)] || | ||
RegExp('\\b' + key + '(?:\\b|\\w*\\d)', 'i').exec(ua) | ||
); | ||
}) && key; | ||
return result || ( | ||
value[product] || | ||
value[0/*Opera 9.25 fix*/, /^[a-z]+/i.exec(product)] || | ||
RegExp('\\b' + (key.pattern || qualify(key)) + '(?:\\b|\\w*\\d)', 'i').exec(ua) | ||
) && (key.label || key); | ||
}); | ||
@@ -411,10 +408,5 @@ } | ||
return reduce(guesses, function(result, guess) { | ||
return result || reduce([guess, camelCase(guess)], function(result, guess) { | ||
return result || RegExp('\\b' + ( | ||
(guess == 'Firefox' && '(?:Firefox|Minefield)') || | ||
(guess == 'IE' && 'MSIE') || | ||
(guess == 'Silk' && '(?:Cloud9|Silk)') || | ||
guess | ||
) + '\\b', 'i').exec(ua); | ||
}) && guess; | ||
return result || RegExp('\\b' + ( | ||
guess.pattern || qualify(guess) | ||
) + '\\b', 'i').exec(ua) && (guess.label || guess); | ||
}); | ||
@@ -431,21 +423,22 @@ } | ||
return reduce(guesses, function(result, guess) { | ||
var pattern = guess.pattern || qualify(guess); | ||
if (!result && (result = | ||
reduce([guess, camelCase(guess)], function(result, guess) { | ||
return result || RegExp('\\b' + guess + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua); | ||
}))) { | ||
RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua))) { | ||
// platform tokens defined at | ||
// http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx | ||
// http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx | ||
data = { | ||
'6.2': '8', | ||
'6.1': 'Server 2008 R2 / 7', | ||
'6.0': 'Server 2008 / Vista', | ||
'5.2': 'Server 2003 / XP 64-bit', | ||
'5.1': 'XP', | ||
'5.0': '2000', | ||
'4.0': 'NT', | ||
'4.9': 'ME' | ||
'6.2': '8', | ||
'6.1': 'Server 2008 R2 / 7', | ||
'6.0': 'Server 2008 / Vista', | ||
'5.2': 'Server 2003 / XP 64-bit', | ||
'5.1': 'XP', | ||
'5.01': '2000 SP1', | ||
'5.0': '2000', | ||
'4.0': 'NT', | ||
'4.90': 'ME' | ||
}; | ||
// detect Windows version from platform tokens | ||
if (/^Win/i.test(result) && | ||
(data = data[0/*Opera 9.25 fix*/, /[456]\.\d/.exec(result)])) { | ||
(data = data[0/*Opera 9.25 fix*/, /[\d.]+$/.exec(result)])) { | ||
result = 'Windows ' + data; | ||
@@ -455,3 +448,4 @@ } | ||
result = format(String(result) | ||
.replace(RegExp(guess + '|' + camelCase(guess), 'i'), guess) | ||
.replace(RegExp(pattern, 'i'), guess.label || guess) | ||
.replace(/ ce$/i, ' CE') | ||
.replace(/hpw/i, 'web') | ||
@@ -463,3 +457,3 @@ .replace(/Macintosh/, 'Mac OS') | ||
.replace(/_/g, '.') | ||
.replace(/[ .]*fc[ \d.]+$/, '') | ||
.replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') | ||
.replace(/x86\.64/gi, 'x86_64') | ||
@@ -480,18 +474,15 @@ .split(' on ')[0]); | ||
return reduce(guesses, function(result, guess) { | ||
var pattern = guess.pattern || qualify(guess); | ||
if (!result && (result = | ||
reduce([guess, camelCase(guess)], function(result, guess) { | ||
return result || | ||
(guess == 'Galaxy S' && /\bGT-I9000\b/i.test(ua) && guess) || | ||
(guess == 'Galaxy S2' && /\bGT-I9100\b/i.test(ua) && guess) || | ||
(guess == 'Kindle Fire' && /\b(?:Cloud9|Silk)\b/i.test(ua) && guess) || | ||
RegExp('\\b' + guess + ' *\\d+[.\\w_]*', 'i').exec(ua) || | ||
RegExp('\\b' + guess + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua); | ||
}))) { | ||
RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) || | ||
RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua) | ||
)) { | ||
// split by forward slash and append product version if needed | ||
if ((result = String(result).split('/'))[1] && !/[\d.]+/.test(result[0])) { | ||
if ((result = String(guess.label || result).split('/'))[1] && !/[\d.]+/.test(result[0])) { | ||
result[0] += ' ' + result[1]; | ||
} | ||
// correct character case and cleanup | ||
guess = guess.label || guess; | ||
result = format(result[0] | ||
.replace(RegExp(guess + '|' + camelCase(guess), 'i'), guess) | ||
.replace(RegExp(pattern, 'i'), guess) | ||
.replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ') | ||
@@ -505,16 +496,11 @@ .replace(RegExp('(' + guess + ')(\\w)', 'i'), '$1 $2')); | ||
/** | ||
* Resolves the version using an array of UA tokens. | ||
* Resolves the version using an array of UA patterns. | ||
* @private | ||
* @param {Array} tokens An array of UA tokens. | ||
* @param {Array} patterns An array of UA patterns. | ||
* @returns {String|Null} The detected version. | ||
*/ | ||
function getVersion(tokens) { | ||
return reduce(tokens, function(result, token) { | ||
return result || reduce([token, camelCase(token)], function(result, token) { | ||
return result || (RegExp(( | ||
(token == 'Firefox' && '(?:Firefox|Minefield)') || | ||
(token == 'Silk' && '(?:Cloud9|Silk)') || | ||
token | ||
) + '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/-]*)', 'i').exec(ua) || 0)[1] || null; | ||
}); | ||
function getVersion(patterns) { | ||
return reduce(patterns, function(result, pattern) { | ||
return result || (RegExp(pattern + | ||
'(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/-]*)', 'i').exec(ua) || 0)[1] || null; | ||
}); | ||
@@ -591,7 +577,6 @@ } | ||
version = getVersion([ | ||
/Mini|Raven|Silk/.test(name) ? name : 'version', | ||
name, | ||
'AdobeAIR', | ||
'Firefox', | ||
'NetFront' | ||
'(?:Cloud9|Opera ?Mini|Raven|Silk)', | ||
'Version', | ||
qualify(name), | ||
'(?:Firefox|Minefield|NetFront)' | ||
]); | ||
@@ -653,5 +638,5 @@ } | ||
else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) { | ||
version = [version, doc.documentMode]; | ||
// we're in compatibility mode when the Trident version + 4 doesn't | ||
// equal the document mode | ||
version = [version, doc.documentMode]; | ||
if ((data = +data[1] + 4) != version[1]) { | ||
@@ -696,7 +681,8 @@ description.push('IE ' + version[1] + ' mode'); | ||
// add mobile postfix | ||
else if ((name == 'IE' || name && !product) && !/Browser/.test(name) && /Mobi/i.test(ua)) { | ||
else if ((name == 'IE' || name && !product && !/Browser/.test(name)) && | ||
(os == 'Windows CE' || /Mobi/i.test(ua))) { | ||
name += ' Mobile'; | ||
} | ||
// detect IE platform preview | ||
else if (name == 'IE' && typeof external == 'object' && !external) { | ||
else if (name == 'IE' && useFeatures && typeof external == 'object' && !external) { | ||
description.unshift('platform preview'); | ||
@@ -714,13 +700,37 @@ } | ||
// http://www.opera.com/support/kb/view/843/ | ||
else if (useFeatures && opera && | ||
(data = parse(ua.replace(reOpera, '') + ';')).name && | ||
!reOpera.test(data.name)) { | ||
layout = ['Presto']; | ||
else if (this != forOwn && ( | ||
(useFeatures && opera) || | ||
(/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) || | ||
(name == 'Firefox' && /OS X (?:\d+\.){2,}/.test(os)) || | ||
(name == 'IE' && ( | ||
(os && !/^Win/.test(os) && version > 5.5) || | ||
/Windows XP/.test(os) && version > 8 || | ||
version == 8 && !/Trident/.test(ua) | ||
)) | ||
) && !reOpera.test(data = parse.call(forOwn, ua.replace(reOpera, '') + ';')) && data.name) { | ||
// when "indentifying" the UA contains both Opera and the other browser's name | ||
data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); | ||
if (reOpera.test(name)) { | ||
if (/IE/.test(data) && os == 'Mac OS') { | ||
os = null; | ||
} | ||
data = 'identify' + data; | ||
} else { | ||
} | ||
// when "masking" the UA contains only the other browser's name | ||
else { | ||
data = 'mask' + data; | ||
name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); | ||
if (operaClass) { | ||
name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); | ||
} else { | ||
name = 'Opera'; | ||
} | ||
if (/IE/.test(data)) { | ||
os = null; | ||
} | ||
if (!useFeatures) { | ||
version = null; | ||
} | ||
} | ||
layout = ['Presto']; | ||
description.push(data); | ||
@@ -732,3 +742,3 @@ } | ||
data = [parseFloat(data), data]; | ||
if (data[1].slice(-1) == '+' && name == 'Safari') { | ||
if (name == 'Safari' && data[1].slice(-1) == '+') { | ||
name = 'WebKit Nightly'; | ||
@@ -738,4 +748,10 @@ prerelease = 'alpha'; | ||
} | ||
// clear incorrect browser versions | ||
else if (version == data[1] || | ||
version == (/Safari\/([\d.]+\+?)/i.exec(ua) || 0)[1]) { | ||
version = null; | ||
} | ||
// use the full Chrome version when available | ||
data = [data[0], (/Chrome\/([\d.]+)/i.exec(ua) || 0)[1]]; | ||
// detect JavaScriptCore | ||
@@ -765,3 +781,3 @@ // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi | ||
/Browser|Lunascape|Maxthon/.test(name) || | ||
/Adobe|Arora|Midori|Phantom|Rekonq|RockMelt|Sleipnir|WebKit/.test(name) && layout[1])) { | ||
/^(?:Adobe|Arora|Midori|Phantom|Rekonq|Rock|Sleipnir|Web)/.test(name) && layout[1])) { | ||
// don't add layout details to description if they are falsey | ||
@@ -791,2 +807,4 @@ (data = layout[layout.length - 1]) && description.push(data); | ||
ua || (ua = null); | ||
/*------------------------------------------------------------------------*/ | ||
@@ -827,3 +845,3 @@ | ||
* @memberOf platform | ||
* @type String | ||
* @type String|Null | ||
*/ | ||
@@ -860,2 +878,9 @@ 'description': description.length ? description.join(' ') : ua, | ||
/** | ||
* The browser's user agent string. | ||
* @memberOf platform | ||
* @type String|Null | ||
*/ | ||
'ua': ua, | ||
// avoid platform object conflicts in browsers | ||
@@ -875,5 +900,5 @@ 'noConflict': noConflict, | ||
// expose platform | ||
// in Narwhal, Node.js, or Ringo | ||
// in Narwhal, Node.js, or RingoJS | ||
if (freeExports) { | ||
forIn(parse(), function(value, key) { | ||
forOwn(parse(), function(value, key) { | ||
freeExports[key] = value; | ||
@@ -884,3 +909,5 @@ }); | ||
else if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { | ||
define(function() { return parse(); }); | ||
define('platform', function() { | ||
return parse(); | ||
}); | ||
} | ||
@@ -887,0 +914,0 @@ // in a browser or Rhino |
@@ -48,3 +48,8 @@ # Platform.js | ||
~~~ js | ||
require(['path/to/platform'], function(platform) { | ||
require({ | ||
'paths': { | ||
'platform': 'path/to/platform' | ||
} | ||
}, | ||
['platform'], function(platform) { | ||
console.log(platform.name); | ||
@@ -58,24 +63,24 @@ }); | ||
// on IE10 x86 platform preview running in IE7 compatibility mode on Windows 7 64 bit edition | ||
platform.name; // IE | ||
platform.version; // 10.0 | ||
platform.layout; // Trident | ||
platform.os; // Windows Server 2008 R2 / 7 x64 | ||
platform.description; // IE 10.0 x86 (platform preview; running in IE 7 mode) on Windows Server 2008 R2 / 7 x64 | ||
platform.name; // 'IE' | ||
platform.version; // '10.0' | ||
platform.layout; // 'Trident' | ||
platform.os; // 'Windows Server 2008 R2 / 7 x64' | ||
platform.description; // 'IE 10.0 x86 (platform preview; running in IE 7 mode) on Windows Server 2008 R2 / 7 x64' | ||
// or on an iPad | ||
platform.name; // Safari | ||
platform.version; // 5.1 | ||
platform.product; // iPad | ||
platform.manufacturer; // Apple | ||
platform.layout; // WebKit | ||
platform.os; // iOS 5.0 | ||
platform.description; // Safari 5.1 on Apple iPad (iOS 5.0) | ||
platform.name; // 'Safari' | ||
platform.version; // '5.1' | ||
platform.product; // 'iPad' | ||
platform.manufacturer; // 'Apple' | ||
platform.layout; // 'WebKit' | ||
platform.os; // 'iOS 5.0' | ||
platform.description; // 'Safari 5.1 on Apple iPad (iOS 5.0)' | ||
// or parsing a given UA string | ||
var info = platform.parse('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7.2; en; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 11.52'); | ||
info.name; // Opera | ||
info.version; // 11.52 | ||
info.layout; // Presto | ||
info.os; // Mac OS X 10.7.2 | ||
info.description; // Opera 11.52 on Mac OS X 10.7.2 | ||
info.name; // 'Opera' | ||
info.version; // '11.52' | ||
info.layout; // 'Presto' | ||
info.os; // 'Mac OS X 10.7.2' | ||
info.description; // 'Opera 11.52 (identifying as Firefox 4.0) on Mac OS X 10.7.2' | ||
~~~ | ||
@@ -85,3 +90,3 @@ | ||
To clone this repository including all submodules, using git 1.6.5 or later: | ||
To clone this repository including all submodules, using Git 1.6.5 or later: | ||
@@ -93,3 +98,3 @@ ~~~ bash | ||
For older git versions, just use: | ||
For older Git versions, just use: | ||
@@ -106,3 +111,3 @@ ~~~ bash | ||
1. Platform.js has been tested in at least Adobe AIR 2.6, Chrome 5-15, Firefox 1.5-8, IE 6-10, Opera 9.25-11.52, Safari 2-5.1.1, Node.js 0.4.8-0.6.1, Narwhal 0.3.2, Ringo 0.7, and Rhino 1.7RC3. | ||
1. Platform.js has been tested in at least Adobe AIR 2.6, Chrome 5-15, Firefox 1.5-8, IE 6-10, Opera 9.25-11.52, Safari 2-5.1.1, Node.js 0.4.8-0.6.1, Narwhal 0.3.2, RingoJS 0.7-0.8, and Rhino 1.7RC3. | ||
<a name="fn1" title="Jump back to footnote 1 in the text." href="#fnref1">↩</a> | ||
@@ -109,0 +114,0 @@ |
@@ -6,3 +6,2 @@ # Instructions | ||
1. Copy/paste `platform.js` into the `src` folder. | ||
2. Copy/paste `AIRIntrospector.js` from some place like `C:\Program Files\Adobe\Adobe Flash Builder 4.5\sdks\4.5.0\frameworks\libs\air\AIRIntrospector.js` into the `src` folder. | ||
3. Copy/paste the contents of the `src` folder into the `bin-debug` folder. | ||
2. Copy/paste `AIRIntrospector.js` from some place like `C:\Program Files\Adobe\Adobe Flash Builder 4.5\sdks\4.5.0\frameworks\libs\air\AIRIntrospector.js` into the `src` folder. |
@@ -8,5 +8,9 @@ (function(window) { | ||
var QUnit = | ||
window.QUnit || | ||
(window.QUnit = load('../vendor/qunit/qunit/qunit.js') || window.QUnit) && | ||
(load('../vendor/qunit-clib/qunit-clib.js'), window.QUnit); | ||
window.QUnit || ( | ||
window.setTimeout || (window.addEventListener = window.setTimeout = / /), | ||
window.QUnit = load('../vendor/qunit/qunit/qunit.js') || window.QUnit, | ||
load('../vendor/qunit-clib/qunit-clib.js'), | ||
(window.addEventListener || 0).test && delete window.addEventListener, | ||
window.QUnit | ||
); | ||
@@ -16,3 +20,4 @@ /** The `platform` object to test */ | ||
window.platform || | ||
(load('../platform.js') || window.platform); | ||
load('../platform.js') || | ||
window.platform; | ||
@@ -22,23 +27,14 @@ /*--------------------------------------------------------------------------*/ | ||
/** | ||
* An iteration utility for arrays and objects. | ||
* Callbacks may terminate the loop by explicitly returning `false`. | ||
* An iteration utility for arrays. | ||
* @private | ||
* @param {Array|Object} object The object to iterate over. | ||
* @param {Array} object The array to iterate over. | ||
* @param {Function} callback The function called per iteration. | ||
* @returns {Array|Object} Returns the object iterated over. | ||
*/ | ||
function each(object, callback) { | ||
function each(array, callback) { | ||
var index = -1, | ||
length = object.length; | ||
length = array.length; | ||
if (length == length >>> 0) { | ||
while (++index < length) { | ||
if (callback(object[index], index, object) === false) { | ||
break; | ||
} | ||
} | ||
} else { | ||
forIn(object, callback); | ||
while (++index < length) { | ||
callback(array[index], index, array); | ||
} | ||
return object; | ||
} | ||
@@ -51,12 +47,7 @@ | ||
* @param {Function} callback The function executed per own property. | ||
* @returns {Object} Returns the object iterated over. | ||
*/ | ||
function forIn(object, callback) { | ||
function forOwn(object, callback) { | ||
for (var key in object) { | ||
if (hasKey(object, key) && | ||
callback(object[key], key, object) === false) { | ||
break; | ||
} | ||
hasKey(object, key) && callback(object[key], key, object); | ||
} | ||
return object; | ||
} | ||
@@ -102,3 +93,3 @@ | ||
string = string == null ? '' : string; | ||
each(object || {}, function(value, key) { | ||
forOwn(object || {}, function(value, key) { | ||
string = string.replace(RegExp('#\\{' + key + '\\}', 'g'), String(value)); | ||
@@ -161,3 +152,3 @@ }); | ||
('return ' + | ||
/\(function[\s\S]+?};\s*}/.exec(code)[0] + | ||
/\(function[\s\S]+?(?=if\s*\(freeExports)/.exec(code)[0] + | ||
' return parse()}(this))') | ||
@@ -724,2 +715,10 @@ .replace('/internal|\\n/i.test(toString.toString())', '!me.likeChrome') | ||
'IE 6.1 on Windows 2000 SP1': { | ||
'ua': 'Mozilla/4.0 (Windows; MSIE 6.1; Windows NT 5.01)', | ||
'layout': 'Trident', | ||
'name': 'IE', | ||
'os': 'Windows 2000 SP1', | ||
'version': '6.1' | ||
}, | ||
'IE 7.0#{beta} on Windows Server 2003 / XP 64-bit': { | ||
@@ -864,2 +863,10 @@ 'ua': 'Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2)', | ||
'IE Mobile 4.01 on Windows CE': { | ||
'ua' : 'Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; 240x320)', | ||
'layout': 'Trident', | ||
'name': 'IE Mobile', | ||
'os': 'Windows CE', | ||
'version': '4.01' | ||
}, | ||
'IE Mobile 7.0 on Samsung OMNIA7 (Windows Phone OS 7.0)': { | ||
@@ -1380,6 +1387,7 @@ 'ua': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; SAMSUNG; OMNIA7)', | ||
'SeaMonkey 1.1.7#{alpha}': { | ||
'SeaMonkey 1.1.7#{alpha} on Haiku': { | ||
'ua': 'Mozilla/5.0 (BeOS; U; Haiku BePC; en-US; rv:1.8.1.10pre) Gecko/20080112 SeaMonkey/1.1.7pre', | ||
'layout': 'Gecko', | ||
'name': 'SeaMonkey', | ||
'os': 'Haiku', | ||
'prerelease': 'alpha', | ||
@@ -1614,2 +1622,9 @@ 'version': '1.1.7#{alpha}' | ||
'WebPositive (like Safari 4.x) on Haiku': { | ||
'ua': 'Mozilla/5.0 (compatible; U; InfiNet 0.1; Haiku) AppleWebKit/527+ (KHTML, like Gecko) WebPositive/527+ Safari/527+', | ||
'layout': 'WebKit', | ||
'name': 'WebPositive', | ||
'os': 'Haiku' | ||
}, | ||
'Lynx/2.8.8dev.3 libwww-FM/2.14 SSL-MM/1.4.1': { | ||
@@ -1648,3 +1663,3 @@ 'ua': 'Lynx/2.8.8dev.3 libwww-FM/2.14 SSL-MM/1.4.1' | ||
test('platform.' + name, function() { | ||
each(Tests, function(value, key) { | ||
forOwn(Tests, function(value, key) { | ||
var platform = getPlatform(value); | ||
@@ -1659,4 +1674,4 @@ value = name == 'description' ? key : value[name]; | ||
test('check null values', function() { | ||
each(Tests, function(value) { | ||
each(getPlatform(value), function(value, key) { | ||
forOwn(Tests, function(value) { | ||
forOwn(getPlatform(value), function(value, key) { | ||
!value && strictEqual(value, null, 'platform.' + key); | ||
@@ -1667,32 +1682,70 @@ }); | ||
test('no ua', function() { | ||
forOwn(getPlatform({}), function(value, key) { | ||
if (typeof value != 'function') { | ||
strictEqual(value, null, 'platform.' + key); | ||
} | ||
}); | ||
}); | ||
test('platform.parse', function() { | ||
var actual = platform.parse('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2'); | ||
var expected = 'Chrome 15.0.874.106 on Mac OS X 10.7.2'; | ||
var parse = function(ua) { return platform.parse(ua + ';'); }; | ||
var actual = parse('Mozilla/5.0 (Windows; U; en-US) AppleWebKit/531.9 (KHTML, like Gecko) AdobeAIR/2.5'); | ||
var expected = 'Adobe AIR 2.5 (like Safari 4.x)'; | ||
equal(actual.description, expected, 'parse Adobe Air'); | ||
actual = parse('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2'); | ||
expected = 'Chrome 15.0.874.106 on Mac OS X 10.7.2'; | ||
equal(actual.description, expected, 'parse Chrome'); | ||
actual = platform.parse('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:8.0) Gecko/20100101 Firefox/8.0'); | ||
actual = parse('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:8.0) Gecko/20100101 Firefox/8.0'); | ||
expected = 'Firefox 8.0 on Mac OS X 10.7'; | ||
equal(actual.description, expected, 'parse Firefox'); | ||
actual = platform.parse('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0)'); | ||
actual = parse('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0)'); | ||
expected = 'IE 7.0 on Windows XP'; | ||
equal(actual.description, expected, 'parse IE'); | ||
actual = platform.parse('Opera/9.80 (Macintosh; Intel Mac OS X 10.7.2; U; Edition Next; en) Presto/2.9.220 Version/12.00'); | ||
actual = parse('Opera/9.80 (Macintosh; Intel Mac OS X 10.7.2; U; Edition Next; en) Presto/2.9.220 Version/12.00'); | ||
expected = 'Opera 12.00 on Mac OS X 10.7.2'; | ||
equal(actual.description, expected, 'parse Opera'); | ||
actual = platform.parse('Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 10.10'); | ||
expected = 'Opera 10.10 on Windows XP'; | ||
equal(actual.description, expected, 'parse Opera description identifying as Firefox'); | ||
actual = parse('Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 10.10'); | ||
expected = 'Opera 10.10 (identifying as Firefox 2.0.0) on Windows XP'; | ||
equal(actual.description, expected, 'parse Opera description identifying as Firefox 2.0.0'); | ||
expected = 'Presto'; | ||
equal(actual.layout, expected, 'parse Opera layout identifying as Firefox'); | ||
equal(actual.layout, expected, 'parse Opera layout identifying as Firefox 2.0.0'); | ||
actual = platform.parse('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/534.51.22 (KHTML, like Gecko) Version/5.1.1 Safari/534.51.22'); | ||
actual = parse('Mozilla/4.0 (compatible; MSIE 8.0; Mac_PowerPC; en) Opera 10.52'); | ||
expected = 'Opera 10.52 (identifying as IE 8.0)'; | ||
equal(actual.description, expected, 'parse Opera description identifying as IE 8.0'); | ||
actual = parse('Mozilla/5.0 (compatible; MSIE 9.0; Mac_PowerPC; en) Opera 12.00'); | ||
expected = 'Opera 12.00 (identifying as IE 9.0)'; | ||
equal(actual.description, expected, 'parse Opera description identifying as IE 9.0'); | ||
actual = parse('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7.2; en; rv:2.0) Gecko/20100101 Firefox/4.0'); | ||
expected = 'Opera (masking as Firefox 4.0) on Mac OS X 10.7.2'; | ||
equal(actual.description, expected, 'parse Opera description masking as Firefox 4.0'); | ||
actual = parse('Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; en)'); | ||
expected = 'Opera (masking as IE 8.0)'; | ||
equal(actual.description, expected, 'parse Opera description masking as IE 8.0'); | ||
actual = parse('Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 5.1; Trident/5.0; en)'); | ||
expected = 'Opera (masking as IE 9.0)'; | ||
equal(actual.description, expected, 'parse Opera description masking as IE 9.0'); | ||
actual = parse('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/534.51.22 (KHTML, like Gecko) Version/5.1.1 Safari/534.51.22'); | ||
expected = 'Safari 5.1.1 on Mac OS X 10.7.2'; | ||
equal(actual.description, expected, 'parse Safari'); | ||
actual = parse('Mozilla/5.0 (X11; U; Cygwin; C -) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) PhantomJS/1.0.0'); | ||
expected = 'PhantomJS 1.0.0 (like Safari 4.x) on Cygwin'; | ||
equal(actual.description, expected, 'parse PhantomJS'); | ||
}); | ||
if (window.document) { | ||
test('platform.noConflict', function() { | ||
test('platform.noConflict', function() { | ||
if (window.document) { | ||
var p = [platform, platform.noConflict()]; | ||
@@ -1702,10 +1755,15 @@ equal(p[0], p[1], 'returns platform object'); | ||
window.platform = p[0]; | ||
}); | ||
} else { | ||
ok(true, 'test skipped'); | ||
ok(true, 'test skipped'); | ||
} | ||
}); | ||
if (window.require) { | ||
test('require("platform")', function() { | ||
equal((platform2 || {}).description, platform.description, 'require("platform")'); | ||
}); | ||
test('require("platform")', function() { | ||
if (window.document && window.require) { | ||
equal((platform2 || {}).description, platform.description, 'require("platform")'); | ||
} else { | ||
ok(true, 'test skipped'); | ||
} | ||
} | ||
}); | ||
@@ -1712,0 +1770,0 @@ /*--------------------------------------------------------------------------*/ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
1234466
49
6192
118
2