YUI的UA检测
YUI.UA是针对javascript的宿主环境检测的一个检测对象,返回的是一系统关于当前宿主的信息
1.对象相关信息列表及userAgent
检测对象o = { ie: 0, //ie Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E) opera: 0, //opera Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36 OPR/16.0.1196.62 gecko: 0, // ff Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0 webkit: 0, //检测webkit内核版本 safari: 0, //safari Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2 chrome: 0, //chrome Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.10 Safari/537.36 mobile: null, //检测是否是手机 Mozilla/5.0 (Linux; U; Android 2.3.6; en-us; Nexus S Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 (Android) air: 0, //检测 Adobe AIR的版本 phantomjs: 0, //phantomjs 是以webkit为核心并提供javascript编程接口(API)的无显示浏览器 ipad: 0, //ipad Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 iphone: 0, //iphone Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 ipod: 0, ios: null, //ios系统 iphone | ipad | ipod android: 0, //android 系统 silk: 0, // 亚马逊推出的基于安卓的平板浏览器 全名为Kindle Silk accel: false, //Kindle Silk是否启动加速 webos: 0, //webos caja: nav && nav.cajaVersion, //google发起的让javascript更安全的caja项目 secure: false, //SSL中是否设置 os: null, //操作系统,目前仅检测window或macintosh nodejs: 0, //nodejs版本 winjs: !!((typeof Windows !== "undefined") && Windows.System), //window8与ie10的应用环境 touchEnabled: false //是否支持触摸 },
2.定义一个公用函数,用于检测版本号
版本检测函数var numberify = function(s) { var c = 0; return parseFloat(s.replace(/\./g, function() { return (c++ === 1) ? '' : '.'; })); },
这个函数的就是将’123.234.42.42424’ => 123.23442
变更一下 :保留第一个符号,后面相同的符号全部去掉
版本检测函数var numberify = function (s) { var i = 0; return parseFloat(s.replace(/\./g,function(){ return ( i++ === 0 ) ? '.' : ''; }) } // '1.2.3.4.5.6' ==> 1.23456 来自http://zhangyaochun.iteye.com/blog/1840297
再变更一下:获取一个寻址
版本检测函数//最快的也是seajs采用的 function dirname (path) { var s = path.match ( /.*(?=\/.*$)/); return ( s ? s[0] : '.' ) + '/'; } //第二种 function dirname(path){ var s = path.split('/').slice(0,-1).join('/'); return s ? s : '.'; } 第三种 function dirname(path){ var s = ('./' + path).replace(/(.*)?\/.*/, '$1').substring(2); return s ? s : '.'; } /* "a.js" ===> "./" * "a/b.js" ===> "a/" * "a/b/c.js" ===> "a/b/" 来自 http://zhangyaochun.iteye.com/blog/1693798 */
3.开始检测
版本检测函数YUI.UA = function (subUA) { //numberify函数 //o对象 //nav,ua赋值 nav = window.navigator ua = subUA || nav && nav.userAgent href = window.location && window.location.href o.userAgent = ua }
a. 安全设置o.secure是根据href中是否以https开始来设置值 (http与https的区 别http://www.cnblogs.com/wxlzhizu/archive/2009/12/09/1620005.html)
o.secure = href && (href.toLowerCase().indexOf(‘https’) === 0);
b. 检测顺序如下 (操作系统 –> 检测内核及是否是手机 –> 检测webkit内核 【opera15+特殊,手机项】 –> 检测不是webkit 【opera低版本】 –> IE
检测顺序if (ua) { //检测操作系统 if ((/windows|win32/i).test(ua)) { o.os = 'windows'; } else if ((/macintosh|mac_powerpc/i).test(ua)) { o.os = 'macintosh'; } else if ((/android/i).test(ua)) { o.os = 'android'; } else if ((/symbos/i).test(ua)) { o.os = 'symbos'; } else if ((/linux/i).test(ua)) { o.os = 'linux'; } else if ((/rhino/i).test(ua)) { o.os = 'rhino'; } // Modern KHTML browsers should qualify as Safari X-Grade if ((/KHTML/).test(ua)) { o.webkit = 1; } if ((/IEMobile|XBLWP7/).test(ua)) { o.mobile = 'windows'; } if ((/Fennec/).test(ua)) { o.mobile = 'gecko'; } // Modern WebKit browsers are at least X-Grade 检测webkit类浏览器 m = ua.match(/AppleWebKit\/([^\s]*)/); if (m && m[1]) { o.webkit = numberify(m[1]); o.safari = o.webkit; if (/PhantomJS/.test(ua)) { m = ua.match(/PhantomJS\/([^\s]*)/); if (m && m[1]) { o.phantomjs = numberify(m[1]); } } // Mobile browser check 手机项 if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) { o.mobile = 'Apple'; // iPhone or iPod Touch m = ua.match(/OS ([^\s]*)/); if (m && m[1]) { m = numberify(m[1].replace('_', '.')); } o.ios = m; o.os = 'ios'; o.ipad = o.ipod = o.iphone = 0; m = ua.match(/iPad|iPod|iPhone/); if (m && m[0]) { o[m[0].toLowerCase()] = o.ios; //设置iphone ipod ipad的版本 } } else { m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/); if (m) { // Nokia N-series, webOS, ex: NokiaN95 o.mobile = m[0]; } if (/webOS/.test(ua)) { o.mobile = 'WebOS'; m = ua.match(/webOS\/([^\s]*);/); if (m && m[1]) { o.webos = numberify(m[1]); } } if (/ Android/.test(ua)) { if (/Mobile/.test(ua)) { o.mobile = 'Android'; } m = ua.match(/Android ([^\s]*);/); if (m && m[1]) { o.android = numberify(m[1]); } } if (/Silk/.test(ua)) { m = ua.match(/Silk\/([^\s]*)\)/); if (m && m[1]) { o.silk = numberify(m[1]); } if (!o.android) { o.android = 2.34; //Hack for desktop mode in Kindle o.os = 'Android'; } if (/Accelerated=true/.test(ua)) { o.accel = true; } } } m = ua.match(/OPR\/(\d+\.\d+)/); //以OPR来作条件是因为opera15+ ua中会有chrome safari OPR的版本号 if (m && m[1]) { // Opera 15+ with Blink (pretends to be both Chrome and Safari) opera15+采用chromium引擎 o.opera = numberify(m[1]); } else { m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/); if (m && m[1] && m[2]) { o.chrome = numberify(m[2]); // Chrome o.safari = 0; //Reset safari back to 0 if (m[1] === 'CrMo') { o.mobile = 'chrome'; } } else { m = ua.match(/AdobeAIR\/([^\s]*)/); if (m) { o.air = m[0]; // Adobe AIR 1.0 or better } } } } if (!o.webkit) { // not webkit // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr) if (/Opera/.test(ua)) { m = ua.match(/Opera[\s\/]([^\s]*)/); if (m && m[1]) { o.opera = numberify(m[1]); } m = ua.match(/Version\/([^\s]*)/); if (m && m[1]) { o.opera = numberify(m[1]); // opera 10+ } if (/Opera Mobi/.test(ua)) { o.mobile = 'opera'; m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/); if (m && m[1]) { o.opera = numberify(m[1]); } } m = ua.match(/Opera Mini[^;]*/); if (m) { o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316 } } else { // not opera or webkit m = ua.match(/MSIE ([^;]*)|Trident.*; rv:([0-9.]+)/); if (m && (m[1] || m[2])) { o.ie = numberify(m[1] || m[2]); } else { // not opera, webkit, or ie m = ua.match(/Gecko\/([^\s]*)/); if (m) { o.gecko = 1; // Gecko detected, look for revision m = ua.match(/rv:([^\s\)]*)/); if (m && m[1]) { o.gecko = numberify(m[1]); if (/Mobile|Tablet/.test(ua)) { o.mobile = "ffos"; } } } } } } }
c. 是否支持触摸检测
触摸if (win && nav && !(o.chrome && o.chrome < 6)) { o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0))); }
d.不是客户端版的js检测
nodejsif (!subUA) { if (typeof process === 'object') { if (process.versions && process.versions.node) { //NodeJS o.os = process.platform; o.nodejs = numberify(process.versions.node); } } YUI.Env.UA = o; }
4.版本比较函数,采用sort中函数的写法
版本比较函数compareVersions = function (a, b) { var aPart, aParts, bPart, bParts, i, len; if (a === b) { return 0; } //转换成数组 aParts = (a + '').split('.'); bParts = (b + '').split('.'); //取两个数组中元素多的为长度进行循环 for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) { aPart = parseInt(aParts[i], 10); bPart = parseInt(bParts[i], 10); /*jshint expr: true*/ isNaN(aPart) && (aPart = 0); isNaN(bPart) && (bPart = 0); if (aPart < bPart) { return -1; } if (aPart > bPart) { return 1; } } return 0; };