Merge branch 'master' into gh-pages

This commit is contained in:
Faisal Salman 2012-09-21 23:22:51 +07:00
commit 1486d1c0b3
3 changed files with 259 additions and 209 deletions

View File

@ -1,7 +1,7 @@
{ {
"title": "UA-Parser.JS", "title": "UA-Parser.JS",
"name": "ua-parser-js", "name": "ua-parser-js",
"version": "0.3.3", "version": "0.4.3",
"author": "Faisal Salman <fyzlman@gmail.com> (http://faisalman.com)", "author": "Faisal Salman <fyzlman@gmail.com> (http://faisalman.com)",
"description": "Lightweight JavaScript-based user-agent string parser", "description": "Lightweight JavaScript-based user-agent string parser",
"keywords": [ "keywords": [

View File

@ -17,13 +17,10 @@ Extract detailed type of web browser, layout engine, operating system, and devic
* `getDevice()` * `getDevice()`
* `getEngine()` * `getEngine()`
* `getOS()` * `getOS()`
* `getResult()`
* `getUA()` * `getUA()`
* `setUA(uastring)` * `setUA(uastring)`
## Properties
* `result`
## Example ## Example
```html ```html
@ -33,7 +30,7 @@ Extract detailed type of web browser, layout engine, operating system, and devic
var parser = new UAParser(); var parser = new UAParser();
// by default it takes ua string from current browser's window.navigator.userAgent // by default it takes ua string from current browser's window.navigator.userAgent
console.log(parser.result); console.log(parser.getResult());
/* /*
/// this will print an object structured like this: /// this will print an object structured like this:
{ {
@ -51,8 +48,9 @@ Extract detailed type of web browser, layout engine, operating system, and devic
version: "" version: ""
}, },
device: { device: {
name: "", model: "",
version: "" type: "",
vendor: ""
} }
} }
*/ */
@ -61,12 +59,15 @@ Extract detailed type of web browser, layout engine, operating system, and devic
var uastr = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.2 (KHTML, like Gecko) Ubuntu/11.10 Chromium/15.0.874.106 Chrome/15.0.874.106 Safari/535.2"; var uastr = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.2 (KHTML, like Gecko) Ubuntu/11.10 Chromium/15.0.874.106 Chrome/15.0.874.106 Safari/535.2";
parser.setUA(uastr); parser.setUA(uastr);
console.log(parser.result.browser); // {name: "Chromium", major: "15", version: "15.0.874.106"} console.log(parser.getResult().browser); // {name: "Chromium", major: "15", version: "15.0.874.106"}
console.log(parser.result.engine); // {name: "AppleWebKit", version: "535.2"} console.log(parser.getResult().device); // {model: undefined, type: undefined, vendor: undefined}
console.log(parser.result.os); // {name: "Ubuntu", version: "11.10"} console.log(parser.getResult().engine); // {name: "AppleWebKit", version: "535.2"}
console.log(parser.getResult().os); // {name: "Ubuntu", version: "11.10"}
// let's take another test please // let's take another test please
console.log(parser.setUA("Mozilla/5.0 (compatible; Konqueror/4.1; OpenBSD) KHTML/4.1.4 (like Gecko)").getOS().name); // "OpenBSD" console.log(parser.setUA("Mozilla/5.0 (compatible; Konqueror/4.1; OpenBSD) KHTML/4.1.4 (like Gecko)").getBrowser().name); // "Konqueror"
console.log(parser.getOS()); // {name: "OpenBSD", version: undefined}
console.log(parser.getEngine()); // {name: "KHTML", version: "4.1.4"}
</script> </script>
``` ```
@ -75,12 +76,9 @@ Extract detailed type of web browser, layout engine, operating system, and devic
```js ```js
var UAParser = require('ua-parser'); var UAParser = require('ua-parser');
var parser = new UAParser(); var parser = new UAParser();
var ua1 = 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.11 (KHTML, like Gecko) Version/7.1.0.7 Safari/534.11'; var uaString = 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.11 (KHTML, like Gecko) Version/7.1.0.7 Safari/534.11';
var ua2 = 'Midori/0.2 (X11; Linux; U; cs-cz) WebKit/531.2+';
console.log(parser.setUA(ua1).getDevice().name); // "PlayBook" console.log(parser.setUA(uaString).getDevice().model); // "PlayBook"
console.log(parser.getOS()) // {name: "RIM Tablet OS", version: "1.0.0"}
console.log(parser.getOS(ua2)) // {name: "Linux", version: undefined}
console.log(parser.getOS()) // {name: "RIM Tablet OS", version: "1.0.0"} console.log(parser.getOS()) // {name: "RIM Tablet OS", version: "1.0.0"}
console.log(parser.getEngine().name); // "AppleWebKit" console.log(parser.getEngine().name); // "AppleWebKit"
``` ```

View File

@ -1,4 +1,4 @@
// UA-Parser.JS v0.3.3 // UA-Parser.JS v0.4.3
// Lightweight JavaScript-based User-Agent string parser // Lightweight JavaScript-based User-Agent string parser
// https://github.com/faisalman/ua-parser-js // https://github.com/faisalman/ua-parser-js
// //
@ -6,40 +6,50 @@
// Dual licensed under GPLv2 & MIT // Dual licensed under GPLv2 & MIT
(function (undefined) { (function (undefined) {
var parser = function UAParser (uastring) {
var ua = uastring || (typeof window !== 'undefined' ? window.navigator.userAgent : ""); 'use strict';
// regexp mapper var mapper = {
var regxMap = function (ua) {
var result = {}, i, j, k, l, m; regex : function () {
var result, i, j, k, l, m, args = arguments;
// loop through all regexes maps // loop through all regexes maps
for (i = 1; i < arguments.length; i += 2) { for (i = 0; i < args.length; i += 2) {
var regex = arguments[i], // odd sequence (2,4,6,..) var regex = args[i], // odd sequence (0,2,4,..)
props = arguments[i + 1]; // even sequence (3,5,7,..) props = args[i + 1]; // even sequence (1,3,5,..)
// build object barebones // construct object barebones
if (typeof result === 'undefined') {
result = {};
for (k = 0; k < props.length; k++) { for (k = 0; k < props.length; k++) {
if (typeof props[k] == 'object') { if (typeof props[k] === 'object') {
result[props[k][0]] = undefined; result[props[k][0]] = undefined;
} else { } else {
result[props[k]] = undefined; result[props[k]] = undefined;
} }
} }
if (this.getUA().toString() === '') {
return result;
}
}
// try matching uastring with regexes // try matching uastring with regexes
for (j = 0; j < regex.length; j++) { for (j = 0; j < regex.length; j++) {
l = regex[j].exec(ua); l = regex[j].exec(this.getUA());
if (!!l) { if (!!l) {
for (k = 0; k < props.length; k++) { for (k = 0; k < props.length; k++) {
m = l[k + 1]; m = l[k + 1];
if (typeof props[k] === 'object' && props[k].length === 2) { if (typeof props[k] === 'object' && props[k].length === 2) {
result[props[k][0]] = props[k][1]; result[props[k][0]] = props[k][1];
} else if (typeof props[k] === 'object' && props[k].length === 3) { } else if (typeof props[k] === 'object' && props[k].length === 3) {
if (typeof props[k][1] === 'function') {
result[props[k][0]] = m ? props[k][1].call(this, m, props[k][2]) : undefined;
} else {
result[props[k][0]] = m ? m.replace(props[k][1], props[k][2]) : undefined; result[props[k][0]] = m ? m.replace(props[k][1], props[k][2]) : undefined;
}
} else { } else {
result[props[k]] = m ? m : undefined; result[props[k]] = m ? m : undefined;
} }
@ -51,64 +61,67 @@
if(!!l) break; // break the loop immediately if match found if(!!l) break; // break the loop immediately if match found
} }
return result; return result;
}; },
var mapper = { string : function (str, map) {
check : function(str, map){
for (var i in map) { for (var i in map) {
if (map.hasOwnProperty(i)) { if (map.hasOwnProperty(i)) {
if (typeof map[i] === 'object' && map[i].length > 0) { if (typeof map[i] === 'object' && map[i].length > 0) {
for (var j = 0; j < map[i].length; j++) { for (var j = 0; j < map[i].length; j++) {
if (str.toLowerCase().indexOf(map[i][j]) !== -1) { if (str.toLowerCase().indexOf(map[i][j].toLowerCase()) !== -1) {
return i; return i;
} }
} }
} else if (str.toLowerCase().indexOf(map[i]) !== -1) { } else if (str.toLowerCase().indexOf(map[i].toLowerCase()) !== -1) {
return i; return i;
} }
} }
} }
return str; return str;
}, }
};
var maps = {
os : { os : {
win : function (match, str1) { windows : {
return mapper.check(str1, { version : {
'ME' : '4.90', 'ME' : '4.90',
'NT 3.11' : 'nt3.51', 'NT 3.11' : 'NT3.51',
'NT 4.0' : 'nt4.0', 'NT 4.0' : 'NT4.0',
'2000' : 'nt 5.0', '2000' : 'NT 5.0',
'XP' : ['nt 5.1', 'nt 5.2'], 'XP' : ['NT 5.1', 'NT 5.2'],
'Vista' : 'nt 6.0', 'Vista' : 'NT 6.0',
'7' : 'nt 6.1', '7' : 'NT 6.1',
'8' : 'nt 6.2' '8' : 'NT 6.2'
}); }
} }
} }
}; };
this.getBrowser = function (uastring) { var regexes = {
return regxMap(uastring || ua, [ browser : [[
// Mixed // Mixed
/(kindle)\/((\d+)?[\w\.]+)/i, // Kindle /(kindle)\/((\d+)?[\w\.]+)/i, // Kindle
/(lunascape|maxthon|netfront|jasmine)[\/\s]?((\d+)?[\w\.]+)/i, // Lunascape/Maxthon/Netfront/Jasmine /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?((\d+)?[\w\.]+)/i,
// Lunascape/Maxthon/Netfront/Jasmine/Blazer
// Presto based // Presto based
/(opera\smini)\/((\d+)?[\w\.-]+)/i, // Opera Mini /(opera\smini)\/((\d+)?[\w\.-]+)/i, // Opera Mini
/(opera\smobi)\/((\d+)?[\w\.-]+)/i, // Opera Mobile /(opera\smobi)\/((\d+)?[\w\.-]+)/i, // Opera Mobile
/(opera).+version\/((\d+)?[\w\.]+)/i, // Opera /(opera).+version\/((\d+)?[\w\.]+)/i, // Opera > 9.80
/(opera)[\/\s]+((\d+)?[\w\.]+)/i, /(opera)[\/\s]+((\d+)?[\w\.]+)/i, // Opera < 9.80
// Trident based // Trident based
/(avant\sbrowser|iemobile|slimbrowser)[\/\s]?((\d+)?[\w\.]*)/i, // Avant/IEMobile/SlimBrowser /(avant\sbrowser|iemobile|slimbrowser)[\/\s]?((\d+)?[\w\.]*)/i, // Avant/IEMobile/SlimBrowser
/ms(ie)\s((\d+)?[\w\.]+)/i, // Internet Explorer /ms(ie)\s((\d+)?[\w\.]+)/i, // Internet Explorer
// Webkit/KHTML based // Webkit/KHTML based
/(chromium|flock|rockmelt|midori|epiphany|silk)\/((\d+)?[\w\.]+)/i, // Chromium/Flock/RockMelt/Midori/Epiphany /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|series60|bolt)\/((\d+)?[\w\.]+)/i,
/(chrome|omniweb|arora|dolfin|[tizenaok]{5}\s?browser)\/((\d+)?[\w\.]+)/i, // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/S60/Bolt
/(chrome|omniweb|arora|dolfin|[tizenoka]{5}\s?browser)\/((\d+)?[\w\.]+)/i,
// Chrome/OmniWeb/Arora/Dolphin/Tizen/Nokia // Chrome/OmniWeb/Arora/Dolphin/Tizen/Nokia
], ['name', 'version', 'major'], [ ], ['name', 'version', 'major'], [
/(?:android.+(crmo|crios))\/((\d+)?[\w\.]+)/i, // Chrome for Android/iOS /(?:android.+(crmo|crios))\/((\d+)?[\w\.]+)/i, // Chrome for Android/iOS
@ -124,13 +137,69 @@
/(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla
// Other // Other
/(lynx|dillo|icab)[\/\s]?((\d+)?[\w\.]+)/i, // Lynx/Dillo/iCab /(lynx|dillo|icab|doris)[\/\s]?((\d+)?[\w\.]+)/i, // Lynx/Dillo/iCab/Doris
], ['name', 'version', 'major']); /(gobrowser)\/?[\d\.]*/i // GoBrowser
}; ], ['name', 'version', 'major']
],
this.getEngine = function (uastring) { device : [[
return regxMap(uastring || ua, [ /\(((ip[honead]+|playbook));/i, // iPod/iPhone/iPad/PlayBook
/(hp).+(touchpad)/i, // HP TouchPad
/(kindle)\/([\w\.]+)/i, // Kindle
/\s(nook)[\w\s]+build\/(\w+)/i, // Nook
/(dell)\s(strea[kpr\s\d]*[\dko])/i // Dell Streak
], ['vendor', 'model', ['type', 'Tablet']], [
/(blackberry)[\s-]?(\w+)/i, // BlackBerry
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|nexus|huawei|meizu)[\s_-]?([\w-]+)*/i,
// BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Nexus/Huawei/Meizu
/(hp)\s([\w\s]+\w)/i, // HP iPAQ
/(asus)-?(\w+)/i // Asus
], ['vendor', 'model', ['type', 'Mobile']], [
/android.+((transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+))/i // Asus Tablets
], [['vendor', 'Asus'], 'model', ['type', 'Tablet']], [
/(sony)\s(tablet\s[ps])/i // Sony Tablets
], ['vendor', 'model', ['type', 'Tablet']], [
/(nintendo|playstation)\s([wids3portablev]+)/i // Nintendo/Playstation
], ['vendor', 'model', ['type', 'Console']], [
/(htc)[;_\s-]+([\w\s]+(?=\))|\w+)*/i, // HTC
/(zte)-(\w+)*/i // ZTE
], ['vendor', ['model', /_/g, ' '], ['type', 'Mobile']], [
/\s((milestone|droid[2x]?))[globa\s]*\sbuild\//i, // Motorola
/(mot)[\s-]?(\w+)*/i
], [['vendor', 'Motorola'], 'model', ['type', 'Mobile']], [
/android.+\s((mz60\d|xoom[\s2]{0,2}))\sbuild\//i
], [['vendor', 'Motorola'], 'model', ['type', 'Tablet']], [
/android.+((sch-i[89]0\d|shw-m380s|gt-p\d{4}|gt-n8000|sgh-t8[56]9))/i
], [['vendor', 'Samsung'], 'model', ['type', 'Tablet']], [ // Samsung
/((s[cgp]h-\w+|gt-\w+|galaxy\snexus))/i,
/(sam[sung]*)[\s-]*(\w+-?[\w-]*)*/i,
/sec-((sgh\w+))/i
], [['vendor', 'Samsung'], 'model', ['type', 'Mobile']], [
/(sie)-(\w+)*/i // Siemens
], [['vendor', 'Siemens'], 'model', ['type', 'Mobile']], [
/(maemo|nokia).*(n900|lumia\s\d+)/i, // Nokia
/(nokia)[\s_-]?([\w-]+)*/i
], [['vendor', 'Nokia'], 'model', ['type', 'Mobile']], [
/android\s3\.[\s\w-;]{10}((a\d{3}))/i // Acer
], [['vendor', 'Acer'], 'model', ['type', 'Tablet']], [
/android\s3\.[\s\w-;]{10}(lg?)-([06cv9]{3,4})/i // LG
], [['vendor', 'LG'], 'model', ['type', 'Tablet']], [
/(lg)[e;\s-]+(\w+)*/i
], [['vendor', 'LG'], 'model', ['type', 'Mobile']]
],
engine : [[
/(presto)\/([\w\.]+)/i, // Presto /(presto)\/([\w\.]+)/i, // Presto
/([aple]*webkit|trident)\/([\w\.]+)/i, // Webkit/Trident /([aple]*webkit|trident)\/([\w\.]+)/i, // Webkit/Trident
@ -138,18 +207,16 @@
], ['name', 'version'], [ ], ['name', 'version'], [
/rv\:([\w\.]+).*(gecko)/i // Gecko /rv\:([\w\.]+).*(gecko)/i // Gecko
], ['version', 'name']); ], ['version', 'name']
}; ],
this.getOS = function (uastring) { os : [[
return regxMap(uastring || ua, [
// Windows based // Windows based
/(windows\sphone\sos|windows)\s?([nt\d\.\s]+\d)/i // Windows /(windows\sphone\sos|windows)\s?([ntce\d\.\s]+\d)/i // Windows
], ['name', ['version', /(.+)/gi, mapper.os.win]], [ ], ['name', ['version', mapper.string, maps.os.windows.version]], [
/(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i
], [['name', 'Windows'], ['version', /(.+)/gi, mapper.os.win]], [ ], [['name', 'Windows'], ['version', mapper.string, maps.os.windows.version]], [
// Mobile/Embedded OS // Mobile/Embedded OS
/(blackberry).+version\/([\w\.]+)/i, // Blackberry /(blackberry).+version\/([\w\.]+)/i, // Blackberry
@ -178,7 +245,7 @@
], ['name', 'version'],[ ], ['name', 'version'],[
/(ip[honead]+).*os\s*([\w]+)*\slike\smac/i // iOS /(ip[honead]+).*os\s*([\w]+)*\slike\smac/i // iOS
], [['name', /.+/g, 'iOS'], ['version', /_/g, '.']], [ ], [['name', 'iOS'], ['version', /_/g, '.']], [
/(mac\sos\sx)\s([\w\s\.]+\w)/i, // Mac OS /(mac\sos\sx)\s([\w\s\.]+\w)/i, // Mac OS
], ['name', ['version', /_/g, '.']], [ ], ['name', ['version', /_/g, '.']], [
@ -186,46 +253,37 @@
// Other // Other
/(haiku)\s(\w+)/i, // Haiku /(haiku)\s(\w+)/i, // Haiku
/(macintosh|unix|minix|beos)[\/\s]?()*/i // UNIX/Minix/BeOS /(macintosh|unix|minix|beos)[\/\s]?()*/i // UNIX/Minix/BeOS
], ['name', 'version']); ], ['name', 'version']
]
}; };
this.getDevice = function (uastring) { var UAParser = function UAParser (uastring) {
return regxMap(uastring || ua, [ var ua = uastring || (typeof window !== 'undefined' ? window.navigator.userAgent : "");
/\((ip[honead]+|playbook);/i, // iPod/iPhone/iPad/PlayBook this.getBrowser = function () {
/(blackberry)[\s-]?(\w+)/i, // BlackBerry return mapper.regex.apply(this, regexes.browser);
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|nexus|zte)[\s_-]?([\w-]+)*/i, };
// BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Nexus/ZTE
/(hp)\s([\w\s]+\w)/i, // HP iPAQ
/(hp).+(touchpad)/i, // HP TouchPad
/(kindle)\/([\w\.]+)/i, // Kindle
/(lg)[e;\s-]+(\w+)*/i, // LG
/(nintendo|playstation)\s([wids3portable]+)/i // Nintendo/Playstation
], ['name', 'version'], [
/(htc)[;_\s-]+([\w\s]+(?=\))|[\w]+)*/i, // HTC this.getDevice = function () {
/(zte)-([\w]+)*/i return mapper.regex.apply(this, regexes.device);
], ['name', ['version', /_/g, ' ']], [ };
/\s((milestone|mz601|droid[2x]?|xoom))[globa\s]*\sbuild\//i, // Motorola this.getEngine = function () {
/(mot)[\s-]?(\w+)*/i return mapper.regex.apply(this, regexes.engine);
], [['name', 'Motorola'], 'version'], [ };
/((s[cgp]h-\w+|gt-\w+|galaxy\snexus))/i, // Samsung this.getOS = function () {
/(sam[sung]*)[\s-]*(\w+-?[\w-]*)*/i, return mapper.regex.apply(this, regexes.os);
/sec-((sgh\w+))/i };
], [['name', 'Samsung'], 'version'], [
/((transfo[prime\s]{4,10}\s\w+|(?:android.*)eeepc))/i // Asus this.getResult = function() {
], [['name', 'Asus'], 'version'], [ return {
browser : this.getBrowser(),
/(sie)-(\w+)*/i // Siemens engine : this.getEngine(),
], [['name', 'Siemens'], 'version'], [ os : this.getOS(),
device : this.getDevice()
/(maemo|nokia).*(n900|lumia\s\d+)/i, // Nokia };
/(nokia)[\s_-]?([\w-]+)*/i
], [['name', 'Nokia'], 'version']);
}; };
this.getUA = function() { this.getUA = function() {
@ -234,12 +292,6 @@
this.setUA = function (uastring) { this.setUA = function (uastring) {
ua = uastring; ua = uastring;
this.result = {
browser : this.getBrowser(),
engine : this.getEngine(),
os : this.getOS(),
device : this.getDevice()
};
return this; return this;
}; };
@ -249,10 +301,10 @@
// check whether script is running inside node.js export as module // check whether script is running inside node.js export as module
if (typeof exports !== 'undefined' && this.toString() !== '[object DOMWindow]') { if (typeof exports !== 'undefined' && this.toString() !== '[object DOMWindow]') {
if (typeof module !== 'undefined' && module.exports) { if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = parser; exports = module.exports = UAParser;
} }
exports.UAParser = parser; exports.UAParser = UAParser;
} else { } else {
this['UAParser'] = parser; window['UAParser'] = UAParser;
} }
})(); })();