mirror of
https://github.com/faisalman/ua-parser-js.git
synced 2026-01-02 20:34:41 +03:00
Move properties inside UAItem class into shared prototype
This commit is contained in:
@@ -1191,189 +1191,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function UAItem (itemType, ua, rgxMap, uaCH) {
|
function UAItem (itemType, ua, rgxMap, uaCH) {
|
||||||
|
|
||||||
this.get = function (prop) {
|
|
||||||
if (!prop) return this.data;
|
|
||||||
return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.set = function (prop, val) {
|
|
||||||
this.data[prop] = val;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setCH = function (ch) {
|
|
||||||
this.uaCH = ch;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.detectFeature = function () {
|
|
||||||
if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {
|
|
||||||
switch (this.itemType) {
|
|
||||||
case BROWSER:
|
|
||||||
// Brave-specific detection
|
|
||||||
if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) {
|
|
||||||
this.set(NAME, 'Brave');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DEVICE:
|
|
||||||
// Chrome-specific detection: check for 'mobile' value of navigator.userAgentData
|
|
||||||
if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
|
|
||||||
this.set(TYPE, MOBILE);
|
|
||||||
}
|
|
||||||
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
|
||||||
if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
|
|
||||||
this.set(MODEL, 'iPad')
|
|
||||||
.set(TYPE, TABLET);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OS:
|
|
||||||
// Chrome-specific detection: check for 'platform' value of navigator.userAgentData
|
|
||||||
if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
|
|
||||||
this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RESULT:
|
|
||||||
var data = this.data;
|
|
||||||
var detect = function (itemType) {
|
|
||||||
return data[itemType]
|
|
||||||
.getItem()
|
|
||||||
.detectFeature()
|
|
||||||
.get();
|
|
||||||
};
|
|
||||||
this.set(BROWSER, detect(BROWSER))
|
|
||||||
.set(CPU, detect(CPU))
|
|
||||||
.set(DEVICE, detect(DEVICE))
|
|
||||||
.set(ENGINE, detect(ENGINE))
|
|
||||||
.set(OS, detect(OS));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.parseUA = function () {
|
|
||||||
if (this.itemType != RESULT) {
|
|
||||||
rgxMapper.call(this.data, this.ua, this.rgxMap);
|
|
||||||
}
|
|
||||||
switch (this.itemType) {
|
|
||||||
case BROWSER:
|
|
||||||
this.set(MAJOR, majorize(this.get(VERSION)));
|
|
||||||
break;
|
|
||||||
case OS:
|
|
||||||
if (this.get(NAME) == 'iOS' && this.get(VERSION) == '18.6') {
|
|
||||||
// Based on the assumption that iOS version is tightly coupled with Safari version
|
|
||||||
var realVersion = /\) Version\/([\d\.]+)/.exec(this.ua); // Get Safari version
|
|
||||||
if (realVersion && parseInt(realVersion[1].substring(0,2), 10) >= 26) {
|
|
||||||
this.set(VERSION, realVersion[1]); // Set as iOS version
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.parseCH = function () {
|
|
||||||
var uaCH = this.uaCH,
|
|
||||||
rgxMap = this.rgxMap;
|
|
||||||
|
|
||||||
switch (this.itemType) {
|
|
||||||
case BROWSER:
|
|
||||||
case ENGINE:
|
|
||||||
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
|
|
||||||
if (brands) {
|
|
||||||
for (var i=0; i<brands.length; i++) {
|
|
||||||
var brandName = brands[i].brand || brands[i],
|
|
||||||
brandVersion = brands[i].version;
|
|
||||||
if (this.itemType == BROWSER &&
|
|
||||||
!/not.a.brand/i.test(brandName) &&
|
|
||||||
(!prevName ||
|
|
||||||
(/Chrom/.test(prevName) && brandName != CHROMIUM) ||
|
|
||||||
(prevName == EDGE && /WebView2/.test(brandName))
|
|
||||||
)) {
|
|
||||||
brandName = strMapper(brandName, browserHintsMap);
|
|
||||||
prevName = this.get(NAME);
|
|
||||||
if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) {
|
|
||||||
this.set(NAME, brandName)
|
|
||||||
.set(VERSION, brandVersion)
|
|
||||||
.set(MAJOR, majorize(brandVersion));
|
|
||||||
}
|
|
||||||
prevName = brandName;
|
|
||||||
}
|
|
||||||
if (this.itemType == ENGINE && brandName == CHROMIUM) {
|
|
||||||
this.set(VERSION, brandVersion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CPU:
|
|
||||||
var archName = uaCH[ARCHITECTURE];
|
|
||||||
if (archName) {
|
|
||||||
if (archName && uaCH[BITNESS] == '64') archName += '64';
|
|
||||||
rgxMapper.call(this.data, archName + ';', rgxMap);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DEVICE:
|
|
||||||
if (uaCH[MOBILE]) {
|
|
||||||
this.set(TYPE, MOBILE);
|
|
||||||
}
|
|
||||||
if (uaCH[MODEL]) {
|
|
||||||
this.set(MODEL, uaCH[MODEL]);
|
|
||||||
if (!this.get(TYPE) || !this.get(VENDOR)) {
|
|
||||||
var reParse = {};
|
|
||||||
rgxMapper.call(reParse, 'droid 9; ' + uaCH[MODEL] + ')', rgxMap);
|
|
||||||
if (!this.get(TYPE) && !!reParse.type) {
|
|
||||||
this.set(TYPE, reParse.type);
|
|
||||||
}
|
|
||||||
if (!this.get(VENDOR) && !!reParse.vendor) {
|
|
||||||
this.set(VENDOR, reParse.vendor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (uaCH[FORMFACTORS]) {
|
|
||||||
var ff;
|
|
||||||
if (typeof uaCH[FORMFACTORS] !== 'string') {
|
|
||||||
var idx = 0;
|
|
||||||
while (!ff && idx < uaCH[FORMFACTORS].length) {
|
|
||||||
ff = strMapper(uaCH[FORMFACTORS][idx++], formFactorsMap);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ff = strMapper(uaCH[FORMFACTORS], formFactorsMap);
|
|
||||||
}
|
|
||||||
this.set(TYPE, ff);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OS:
|
|
||||||
var osName = uaCH[PLATFORM];
|
|
||||||
if(osName) {
|
|
||||||
var osVersion = uaCH[PLATFORMVER];
|
|
||||||
if (osName == WINDOWS) osVersion = (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10');
|
|
||||||
this.set(NAME, osName)
|
|
||||||
.set(VERSION, osVersion);
|
|
||||||
}
|
|
||||||
// Xbox-Specific Detection
|
|
||||||
if (this.get(NAME) == WINDOWS && uaCH[MODEL] == 'Xbox') {
|
|
||||||
this.set(NAME, 'Xbox')
|
|
||||||
.set(VERSION, undefined);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RESULT:
|
|
||||||
var data = this.data;
|
|
||||||
var parse = function (itemType) {
|
|
||||||
return data[itemType]
|
|
||||||
.getItem()
|
|
||||||
.setCH(uaCH)
|
|
||||||
.parseCH()
|
|
||||||
.get();
|
|
||||||
};
|
|
||||||
this.set(BROWSER, parse(BROWSER))
|
|
||||||
.set(CPU, parse(CPU))
|
|
||||||
.set(DEVICE, parse(DEVICE))
|
|
||||||
.set(ENGINE, parse(ENGINE))
|
|
||||||
.set(OS, parse(OS));
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
setProps.call(this, [
|
setProps.call(this, [
|
||||||
['itemType', itemType],
|
['itemType', itemType],
|
||||||
['ua', ua],
|
['ua', ua],
|
||||||
@@ -1381,10 +1198,191 @@
|
|||||||
['rgxMap', rgxMap],
|
['rgxMap', rgxMap],
|
||||||
['data', createIData(this, itemType)]
|
['data', createIData(this, itemType)]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UAItem.prototype.get = function (prop) {
|
||||||
|
if (!prop) return this.data;
|
||||||
|
return this.data.hasOwnProperty(prop) ? this.data[prop] : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
UAItem.prototype.set = function (prop, val) {
|
||||||
|
this.data[prop] = val;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
UAItem.prototype.setCH = function (ch) {
|
||||||
|
this.uaCH = ch;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
UAItem.prototype.detectFeature = function () {
|
||||||
|
if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {
|
||||||
|
switch (this.itemType) {
|
||||||
|
case BROWSER:
|
||||||
|
// Brave-specific detection
|
||||||
|
if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) {
|
||||||
|
this.set(NAME, 'Brave');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DEVICE:
|
||||||
|
// Chrome-specific detection: check for 'mobile' value of navigator.userAgentData
|
||||||
|
if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
|
||||||
|
this.set(TYPE, MOBILE);
|
||||||
|
}
|
||||||
|
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
||||||
|
if (this.get(MODEL) == 'Macintosh' && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
|
||||||
|
this.set(MODEL, 'iPad')
|
||||||
|
.set(TYPE, TABLET);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OS:
|
||||||
|
// Chrome-specific detection: check for 'platform' value of navigator.userAgentData
|
||||||
|
if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
|
||||||
|
this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RESULT:
|
||||||
|
var data = this.data;
|
||||||
|
var detect = function (itemType) {
|
||||||
|
return data[itemType]
|
||||||
|
.getItem()
|
||||||
|
.detectFeature()
|
||||||
|
.get();
|
||||||
|
};
|
||||||
|
this.set(BROWSER, detect(BROWSER))
|
||||||
|
.set(CPU, detect(CPU))
|
||||||
|
.set(DEVICE, detect(DEVICE))
|
||||||
|
.set(ENGINE, detect(ENGINE))
|
||||||
|
.set(OS, detect(OS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
UAItem.prototype.parseUA = function () {
|
||||||
|
if (this.itemType != RESULT) {
|
||||||
|
rgxMapper.call(this.data, this.ua, this.rgxMap);
|
||||||
|
}
|
||||||
|
switch (this.itemType) {
|
||||||
|
case BROWSER:
|
||||||
|
this.set(MAJOR, majorize(this.get(VERSION)));
|
||||||
|
break;
|
||||||
|
case OS:
|
||||||
|
if (this.get(NAME) == 'iOS' && this.get(VERSION) == '18.6') {
|
||||||
|
// Based on the assumption that iOS version is tightly coupled with Safari version
|
||||||
|
var realVersion = /\) Version\/([\d\.]+)/.exec(this.ua); // Get Safari version
|
||||||
|
if (realVersion && parseInt(realVersion[1].substring(0,2), 10) >= 26) {
|
||||||
|
this.set(VERSION, realVersion[1]); // Set as iOS version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
UAItem.prototype.parseCH = function () {
|
||||||
|
var uaCH = this.uaCH,
|
||||||
|
rgxMap = this.rgxMap;
|
||||||
|
|
||||||
|
switch (this.itemType) {
|
||||||
|
case BROWSER:
|
||||||
|
case ENGINE:
|
||||||
|
var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
|
||||||
|
if (brands) {
|
||||||
|
for (var i=0; i<brands.length; i++) {
|
||||||
|
var brandName = brands[i].brand || brands[i],
|
||||||
|
brandVersion = brands[i].version;
|
||||||
|
if (this.itemType == BROWSER &&
|
||||||
|
!/not.a.brand/i.test(brandName) &&
|
||||||
|
(!prevName ||
|
||||||
|
(/Chrom/.test(prevName) && brandName != CHROMIUM) ||
|
||||||
|
(prevName == EDGE && /WebView2/.test(brandName))
|
||||||
|
)) {
|
||||||
|
brandName = strMapper(brandName, browserHintsMap);
|
||||||
|
prevName = this.get(NAME);
|
||||||
|
if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) {
|
||||||
|
this.set(NAME, brandName)
|
||||||
|
.set(VERSION, brandVersion)
|
||||||
|
.set(MAJOR, majorize(brandVersion));
|
||||||
|
}
|
||||||
|
prevName = brandName;
|
||||||
|
}
|
||||||
|
if (this.itemType == ENGINE && brandName == CHROMIUM) {
|
||||||
|
this.set(VERSION, brandVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CPU:
|
||||||
|
var archName = uaCH[ARCHITECTURE];
|
||||||
|
if (archName) {
|
||||||
|
if (archName && uaCH[BITNESS] == '64') archName += '64';
|
||||||
|
rgxMapper.call(this.data, archName + ';', rgxMap);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DEVICE:
|
||||||
|
if (uaCH[MOBILE]) {
|
||||||
|
this.set(TYPE, MOBILE);
|
||||||
|
}
|
||||||
|
if (uaCH[MODEL]) {
|
||||||
|
this.set(MODEL, uaCH[MODEL]);
|
||||||
|
if (!this.get(TYPE) || !this.get(VENDOR)) {
|
||||||
|
var reParse = {};
|
||||||
|
rgxMapper.call(reParse, 'droid 9; ' + uaCH[MODEL] + ')', rgxMap);
|
||||||
|
if (!this.get(TYPE) && !!reParse.type) {
|
||||||
|
this.set(TYPE, reParse.type);
|
||||||
|
}
|
||||||
|
if (!this.get(VENDOR) && !!reParse.vendor) {
|
||||||
|
this.set(VENDOR, reParse.vendor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (uaCH[FORMFACTORS]) {
|
||||||
|
var ff;
|
||||||
|
if (typeof uaCH[FORMFACTORS] !== 'string') {
|
||||||
|
var idx = 0;
|
||||||
|
while (!ff && idx < uaCH[FORMFACTORS].length) {
|
||||||
|
ff = strMapper(uaCH[FORMFACTORS][idx++], formFactorsMap);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ff = strMapper(uaCH[FORMFACTORS], formFactorsMap);
|
||||||
|
}
|
||||||
|
this.set(TYPE, ff);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OS:
|
||||||
|
var osName = uaCH[PLATFORM];
|
||||||
|
if(osName) {
|
||||||
|
var osVersion = uaCH[PLATFORMVER];
|
||||||
|
if (osName == WINDOWS) osVersion = (parseInt(majorize(osVersion), 10) >= 13 ? '11' : '10');
|
||||||
|
this.set(NAME, osName)
|
||||||
|
.set(VERSION, osVersion);
|
||||||
|
}
|
||||||
|
// Xbox-Specific Detection
|
||||||
|
if (this.get(NAME) == WINDOWS && uaCH[MODEL] == 'Xbox') {
|
||||||
|
this.set(NAME, 'Xbox')
|
||||||
|
.set(VERSION, undefined);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RESULT:
|
||||||
|
var data = this.data;
|
||||||
|
var parse = function (itemType) {
|
||||||
|
return data[itemType]
|
||||||
|
.getItem()
|
||||||
|
.setCH(uaCH)
|
||||||
|
.parseCH()
|
||||||
|
.get();
|
||||||
|
};
|
||||||
|
this.set(BROWSER, parse(BROWSER))
|
||||||
|
.set(CPU, parse(CPU))
|
||||||
|
.set(DEVICE, parse(DEVICE))
|
||||||
|
.set(ENGINE, parse(ENGINE))
|
||||||
|
.set(OS, parse(OS));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
function UAParser (ua, extensions, headers) {
|
function UAParser (ua, extensions, headers) {
|
||||||
|
|
||||||
if (typeof ua === TYPEOF.OBJECT) {
|
if (typeof ua === TYPEOF.OBJECT) {
|
||||||
|
|||||||
Reference in New Issue
Block a user