2 // ------------------------------------------------------------------------- //
\r
3 // ------------ local variables -------------------------------------------- //
\r
4 // ------------------------------------------------------------------------- //
\r
7 * UserAgent の関する定数を保持する。
\r
12 var X_UA = X[ 'UA' ] = {};
\r
15 var dua = navigator.userAgent,
\r
16 dav = navigator.appVersion,
\r
17 tv = parseFloat(dav),
\r
18 sys = navigator.platform,
\r
19 tridentToVer, i, j, v;
\r
21 console.log( ' userAgent : ' + dua );
\r
23 console.log( ' appVersion : ' + dav );
\r
25 console.log( ' platform : ' + sys );
\r
28 // TODO 3DS, DSi, WiiU
\r
30 if( sys.indexOf( 'iP' ) === 0 ){
\r
32 v = dua.split( 'OS ' )[ 1 ].split( '_' );
\r
33 i = window.devicePixelRatio === 1;
\r
35 * @alias X.UA.iOSMajor
\r
38 X_UA[ 'iOSMajor' ] = parseFloat( v[ 0 ] ) || 0;
\r
40 * @alias X.UA.iOSMinor
\r
43 X_UA[ 'iOSMinor' ] = parseFloat( v[ 1 ] ) || 0;
\r
45 * @alias X.UA.iOSPatch
\r
48 X_UA[ 'iOSPatch' ] = parseFloat( v[ 2 ] ) || 0;
\r
53 X_UA[ 'iOS' ] = X_UA[ 'iOSMajor' ] + X_UA[ 'iOSMinor' ] / 10;
\r
55 if( screen.width === screen.height * 1.5 || screen.width * 1.5 === screen.height ){
\r
56 v = true; // 4:3 model
\r
59 if( sys === 'iPhone' ){
\r
61 * @alias X.UA.iPhone
\r
64 X_UA[ 'iPhone' ] = true;
\r
68 * @alias X.UA.iPhone_4s
\r
71 X_UA[ 'iPhone_4s' ] = true;
\r
76 * @alias X.UA.iPhone_3GS
\r
79 X_UA[ 'iPhone_3GS' ] = true;
\r
81 //alert( 'iPhone ' + ( X_UA[ 'iPhone_3GS' ] ? '3GS以下' : X_UA[ 'iPhone_4s' ] ? '4s以下' : '5以上' ) );
\r
83 if( sys === 'iPad' ){
\r
88 X_UA[ 'iPad' ] = true;
\r
91 * iPad2以下または初代iPad mini 以下
\r
92 * @alias X.UA.iPad_2Mini1
\r
95 X_UA[ 'iPad_2Mini1' ] = true;
\r
98 if( sys === 'iPod' ){
\r
103 X_UA[ 'iPod' ] = true;
\r
107 * @alias X.UA.iPod_3
\r
110 X_UA[ 'iPod_3' ] = true;
\r
115 * @alias X.UA.iPod_4
\r
118 X_UA[ 'iPod_4' ] = true;
\r
120 //alert( 'iPod touch ' + ( X_UA[ 'iPod_3' ] ? '3以下' : X_UA[ 'iPod_4' ] ? '4以下' : '5以上' ) );
\r
123 console.log( '>> iOS : ' + X_UA[ 'iOS' ] );
\r
125 if( dua.indexOf( 'hp-tablet' ) !== -1 || dua.indexOf( 'webOS' ) !== -1 ){
\r
127 * http://user-agent-string.info/list-of-ua/os-detail?os=webOS
\r
128 * @alias X.UA.webOS
\r
131 X_UA[ 'webOS' ] = true; // webOS
\r
133 if( sys.indexOf( 'Win' ) + 1 ){
\r
134 console.log( 'Win' );
\r
136 * @alias X.UA.Windows
\r
139 X_UA[ 'Windows' ] = true;
\r
146 * @alias X.UA.Win16
\r
147 * @alias X.UA.Win32
\r
148 * @alias X.UA.Win64
\r
149 * @alias X.UA.WinCE
\r
152 X_UA[ sys ] = true;
\r
156 if( sys.indexOf( 'Mac' ) + 1 ){
\r
157 console.log( 'Mac' );
\r
162 X_UA[ 'Mac' ] = true;
\r
164 case 'MacPowerPC' :
\r
166 * @alias X.UA.MacPPC
\r
169 X_UA[ 'MacPPC' ] = true;
\r
175 * @alias X.UA.MacPPC
\r
176 * @alias X.UA.Mac68K
\r
177 * @alias X.UA.MacIntel
\r
180 X_UA[ sys ] = true;
\r
183 if( ( sys.indexOf( 'Linux' ) + 1 ) || ( sys.indexOf( 'Android' ) + 1 ) ){
\r
184 console.log( 'Linux' );
\r
186 * @alias X.UA.Linux
\r
189 X_UA[ 'Linux' ] = true;
\r
191 if( ( i = dua.indexOf( 'Android' ) ) !== -1 ){
\r
193 * Firefox で Version が取れない!
\r
194 * http://bizmakoto.jp/bizid/articles/1207/31/news004.html
\r
195 * Chrome Android 4.0以上 Google
\r
196 * Dolphin Browser HD Android 2.0.1以上 Mobotap
\r
197 * Firefox Android 2.2以上 Mozilla
\r
198 * Opera Mobile Android 1.6以上 Opera Software ASA
\r
199 * Sleipnir Mobile Android 2.1以上 Fenrir
\r
200 * @alias X.UA.Android
\r
203 X_UA[ 'Android' ] = parseFloat( dua.substr( i + 8 ) ) || 0.1;
\r
204 console.log( '>> Android : ' + X_UA[ 'Android' ] );
\r
208 if( window.opera ){
\r
209 i = dua.indexOf( 'Opera' ); // Opera/
\r
210 j = dua.indexOf( 'Version/' );
\r
212 * @alias X.UA.Opera
\r
215 X_UA[ 'Opera' ] = v = Math.max(
\r
216 i !== -1 ? parseFloat( dua.substr( i + 6 ) ) : 0,
\r
217 j !== -1 ? parseFloat( dua.substr( j + 8 ) ) : 0,
\r
220 * memo:closure compiler で minify するとOpera7で動かない
\r
221 * --compilation_level WHITESPACE_ONLY --formatting pretty_print <- 動く
\r
222 * @alias X.UA.Opera7
\r
225 X_UA[ 'Opera7' ] = v < 8;
\r
227 * @alias X.UA.Opera78
\r
230 X_UA[ 'Opera78' ] = v < 9;
\r
232 * @alias X.UA.OperaMini
\r
235 X_UA[ 'OperaMini' ] = 0 < dua.indexOf('Opera Mini');
\r
237 * @alias X.UA.OperaMobile
\r
240 X_UA[ 'OperaMobile' ] = 0 < dua.indexOf('Opera Mobi');
\r
242 * @alias X.UA.OperaTablet
\r
245 X_UA[ 'OperaTablet' ] = 0 < dua.indexOf('Opera Tablet');
\r
250 X_UA[ 'Wii' ] = dua.indexOf( 'Nintendo Wii' ) !== -1;
\r
255 X_UA[ 'NDS' ] = dua.indexOf( 'Nitro' ) !== -1;
\r
256 console.log( '>> Opera : ' + v );
\r
260 // Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko
\r
261 if( document.all || dav.indexOf( 'Trident/' ) !== -1 ){
\r
263 * @alias X.UA.ActiveX
\r
266 X_UA[ 'ActiveX' ] = !!window[ 'ActiveXObject' ];
\r
268 * documentモードを考慮しないIEのバージョン
\r
272 X_UA[ '_IE' ] = parseFloat(dua.split('MSIE ')[1]) || parseFloat(dua.split('rv:')[1]) || parseFloat(dav.split('MSIE ')[1]) || 0;
\r
274 * IE11 の互換モードの navigator.appVersion にも Trident/7.0 が書かれているため互換モードか?判定ができる
\r
275 * 互換モードでは Silverlight でエラーが出る?
\r
276 * @alias X.UA.Trident
\r
279 X_UA[ 'Trident' ] = parseFloat(dav.split('Trident/')[1]) || 0;
\r
281 * documentモードを考慮したIEのバージョン
\r
285 X_UA[ 'IE' ] = v = document.documentMode || X_UA[ '_IE' ];
\r
286 tridentToVer = X_UA[ 'Trident' ] ? ( X_UA[ 'Trident' ] + 4 | 0 ) : X_UA[ '_IE' ];
\r
288 * IE10 以上の互換モードを使用している場合、そのバージョン
\r
289 * @alias X.UA.IECompat
\r
292 X_UA[ 'IECompat' ] = /* v !== X_UA[ '_IE' ] || */ tridentToVer !== X_UA[ '_IE' ] && tridentToVer;
\r
297 X_UA[ 'IE4' ] = v && v < 5;
\r
302 X_UA[ 'IE5' ] = 5 <= v && v < 5.5;
\r
307 X_UA[ 'IE55' ] = 5.5 <= v && v < 6;
\r
312 X_UA[ 'IE5x' ] = X_UA[ 'IE5' ] || X_UA[ 'IE55' ];
\r
317 X_UA[ 'IE6' ] = 6 <= v && v < 7;
\r
322 X_UA[ 'IE7' ] = 7 <= v && v < 8;
\r
327 X_UA[ 'IE8' ] = 8 <= v && v < 9;
\r
332 X_UA[ 'IE9' ] = 9 <= v && v < 10;
\r
334 * @alias X.UA.MacIE
\r
337 X_UA[ 'MacIE' ] = X_UA[ 'Mac' ];
\r
339 * @alias X.UA.IEMobile
\r
342 X_UA[ 'IEMobile' ] = dua.toLowerCase().indexOf( 'iemobile' ) !== -1 || X_UA[ 'WinCE' ];
\r
344 * @alias X.UA.WinPhone
\r
347 X_UA[ 'WinPhone' ] = dua.toLowerCase().indexOf( 'windows phone' ) !== -1 || 0 < dav.indexOf( 'ZuneWP' ); // ZuneWP は IEM のデスクトップモードで登場する
\r
348 console.log( '>> IE : ' + v + ' ActiveX : ' + X_UA[ 'ActiveX' ] );
\r
349 // TODO XBox360, XBox1, Modern or Desktop, Standalone
\r
354 if( ( i = dua.indexOf( 'NetFront\/' ) !== -1 ) ){
\r
356 * http://qa.support.sony.jp/solution/S0812181056444/common/nfb34_dom_200jp/dom_dom0_JP.html
\r
357 * @alias X.UA.NetFront
\r
360 X_UA[ 'NetFront' ] = parseFloat( dua.substr( i + 9 ) ) || 0.1;
\r
361 console.log( '>> NetFront : ' + X_UA[ 'NetFront' ] );
\r
365 if( X_UA[ 'Linux' ] && tv === 2 && dua.indexOf( 'Sony\/COM2\/' ) !== -1 ){
\r
366 X_UA[ 'NetFront' ] = 3.4;
\r
367 console.log( '>> NetFront : ' + X_UA[ 'NetFront' ] );
\r
371 if( ( i = dua.toUpperCase().indexOf( 'PLAYSTATION 3' ) !== -1 ) ){
\r
373 * PlayStation 3 システムバージョン 4.10 未満の SONY 独自ブラウザ
\r
374 * http://www.useragentstring.com/pages/Playstation%203/
\r
375 * Mozilla/5.0 (PLAYSTATION 3; 3.55)
\r
376 * Mozilla/4.0 (PS3 (PlayStation 3); 1.00)
\r
377 * https://github.com/Famous/famous/blob/1a02c8084587d80519ea4bd3b55649ab32ee2e65/examples/assets/lib/require.js
\r
378 * PS3 ブラウザのロードイベントについて
\r
382 X_UA[ 'PS3' ] = parseFloat( dua.substr( i + 15 ) ) || 0.1;
\r
383 console.log( '>> PS3 : ' + X_UA[ 'PS3' ] );
\r
387 if( ( i = dua.indexOf( 'iCab' ) !== -1 ) ){
\r
389 * http://www.useragentstring.com/pages/iCab/
\r
390 * iCab/3.0.2 (Macintosh; U; PPC Mac OS X)
\r
391 * Mozilla/5.0 (Macintosh; U; PPC Mac OS; en) iCab 3
\r
395 X_UA[ 'iCab' ] = parseFloat( dua.substr( i + 5 ) ) || 0.1;
\r
396 console.log( '>> iCab : ' + X_UA[ 'iCab' ] );
\r
400 if( 0 < dua.indexOf( 'Gecko\/' ) && ( i = dua.indexOf( 'rv:' ) ) ){
\r
401 v = dua.substr( i + 3 ).split( '.' );
\r
403 * メジャーバージョン + マイナーバージョン
\r
404 * @alias X.UA.Gecko
\r
407 X_UA[ 'Gecko' ] = parseFloat( v[ 0 ] ) || 0 +
\r
408 ( parseFloat( v[ 1 ] ) || 0 ) / 10 +
\r
409 ( parseFloat( v[ 2 ] ) || 0 ) / 100;
\r
411 * @alias X.UA.GeckoMajor
\r
414 X_UA[ 'GeckoMajor' ] = parseFloat( v[ 0 ] ) || 0;
\r
416 * @alias X.UA.GeckoMinor
\r
419 X_UA[ 'GeckoMinor' ] = parseFloat( v[ 1 ] ) || 0;
\r
421 * @alias X.UA.GeckoPatch
\r
424 X_UA[ 'GeckoPatch' ] = parseFloat( v[ 2 ] ) || 0;
\r
427 if( ( i = dua.indexOf( 'Fennec/' ) ) !== -1 ){
\r
429 * Mozilla/5.0 (Android; Linux armv7l; rv:9.0) Gecko/20111216 Firefox/9.0 Fennec/9.0
\r
430 * @alias X.UA.Fennec
\r
433 X_UA[ 'Fennec' ] = parseFloat( dua.substr( i + 7 ) );
\r
434 console.log( '>> Fennec : ' + X_UA[ 'Fennec' ] + ', Gecko : ' + X_UA[ 'Gecko' ] );
\r
440 //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3
\r
441 if( ( i = dua.indexOf( 'Netscape6/' ) ) !== -1 ){
\r
446 X_UA[ 'NN' ] = parseFloat( dua.substr( i + 10 ) ) || 6;
\r
451 X_UA[ 'NN6' ] = true;
\r
452 console.log( '>> NN : ' + X_UA[ 'NN' ] + ', Gecko : ' + X_UA[ 'Gecko' ] );
\r
455 //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)
\r
456 //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20070321 Netscape/8.1.3
\r
457 if( ( i = dua.indexOf( 'Netscape/' ) ) !== -1 ){
\r
458 X_UA[ 'NN' ] = parseFloat( dua.substr( i + 9 ) ) || 7;
\r
459 console.log( '>> NN : ' + X_UA[ 'NN' ] + ', Gecko : ' + X_UA[ 'Gecko' ] );
\r
462 //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080219 Firefox/2.0.0.12 Navigator/9.0.0.6
\r
463 if( ( i = dua.indexOf( 'Navigator/' ) ) !== -1 ){
\r
464 X_UA[ 'NN' ] = parseFloat( dua.substr( i + 10 ) ) || 9;
\r
465 console.log( '>> NN : ' + X_UA[ 'NN' ] + ', Gecko : ' + X_UA[ 'Gecko' ] );
\r
469 console.log( '>> Gecko : ' + X_UA[ 'Gecko' ] );
\r
473 if( window.chrome ){
\r
475 * @alias X.UA.Blink
\r
478 X_UA[ 'Blink' ] = tv;
\r
479 console.log( '>>Blink : ' + X_UA[ 'Blink' ] );
\r
482 if( dav.indexOf( 'Konqueror' ) !== -1 ){
\r
484 * @alias X.UA.Khtml
\r
487 X_UA[ 'Khtml' ] = tv;
\r
488 console.log( '>>Khtml : ' + X_UA[ 'Khtml' ] );
\r
491 if( ( i = dua.indexOf( 'Android ' ) ) !== -1 ){
\r
494 * @alias X.UA.AndroidBrowser
\r
497 X_UA[ 'AndroidBrowser' ] = i = parseFloat( dua.substr( i + 8 ) ) || 0.1;
\r
499 * @alias X.UA.AndroidBrowser1
\r
502 X_UA[ 'AndroidBrowser1' ] = 1 <= i && i < 2;
\r
504 * @alias X.UA.AndroidBrowser2
\r
507 X_UA[ 'AndroidBrowser2' ] = 2 <= i && i < 3;
\r
509 * @alias X.UA.AndroidBrowser3
\r
512 X_UA[ 'AndroidBrowser3' ] = 3 <= i && i < 4;
\r
514 * @alias X.UA.AndroidBrowser4
\r
517 X_UA[ 'AndroidBrowser4' ] = 4 <= i && i < 5;
\r
519 * @alias X.UA.AndroidBrowser5
\r
522 X_UA[ 'AndroidBrowser5' ] = 5 <= i && i < 6;
\r
523 console.log( '>> AndroidBrowser : ' + X_UA[ 'Android' ] );
\r
525 i = parseFloat(dua.split('WebKit\/')[1]);
\r
527 * @alias X.UA.AndroidBrowserWebkit
\r
530 X_UA[ 'AndroidBrowserWebkit' ] = i;
\r
531 alert( 'AudioSprite調査:Android標準ブラウザ Webkit Version ' + i );
\r
534 if( i = parseFloat(dua.split('WebKit\/')[1]) ){
\r
536 * @alias X.UA.WebKit
\r
539 X_UA[ 'WebKit' ] = i;
\r
541 if( v = parseFloat(dua.split('Chrome\/')[1]) ){
\r
543 * @alias X.UA.Chrome
\r
546 X_UA[ 'Chrome' ] = v;
\r
549 // TODO webkit Opera
\r
551 console.log( '>>Webkit : ' + X_UA[ 'WebKit' ] );
\r
553 if( i && !X_UA[ 'Chrome' ] && dua.indexOf( 'Safari' ) !== -1 ){
\r
554 if( dav.indexOf( 'Version/' ) !== -1 ){
\r
556 * @alias X.UA.Safari
\r
559 X_UA[ 'Safari' ] = parseFloat( dav.split('Version/')[1] );
\r
562 X_UA[ 'Safari' ] = i < 73 ? 0.8 :
\r
570 i <= 525.25 ? 3.1 : 3.2;
\r
575 console.log( '>> Webkit : ' + X_UA[ 'WebKit' ] + ' Safari : ' + X_UA[ 'Safari' ] );
\r
578 if( dua.toLowerCase().indexOf( 'iris' ) !== -1 ){
\r
580 * http://www.useragentstring.com/pages/Iris/
\r
584 X_UA[ 'Iris' ] = true;
\r
587 if( // Kobo Mozilla/5.0 (Linux; U; Android 2.0; en-us;) AppleWebKit/533.1 (KHTML, like Gecko) Verson/4.0 Mobile Safari/533.1 (Kobo Touch)
\r
588 dua.indexOf( 'Kobo' ) !== -1 ||
\r
589 // Kindle paperwhite Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+
\r
590 dua.indexOf( 'Kindle' ) !== -1 ||
\r
591 // Sony Reader Mozilla/5.0 (Linux; U; ja-jp; EBRD1101; EXT) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
\r
592 dua.indexOf( 'EBRD' ) !== -1
\r
595 * Kobo, Kindle, Sony Reader
\r
599 X_UA[ 'EInk' ] = true;
\r
608 * http://d.hatena.ne.jp/t-uchima/20051003/p1
\r
609 * MacIEにはattachEventが一応あるけどwindow.attachEventとdocument.attachEventしかなく他の要素にはattachEventはない。
\r
611 if( X_UA[ 'IE4' ] && X_UA[ 'IE' ] < 5 ){ // ie4 & iemobi4 & macie4.x
\r
612 X_UA_DOM.IE4 = true;
\r
613 X_UA_EVENT.IE4 = true;
\r
615 if( X_UA[ 'MacIE' ] ){
\r
616 X_UA_DOM.W3C = true;
\r
617 X_UA_EVENT.IE = true;
\r
619 if( document.getElementById ){
\r
620 X_UA_DOM.W3C = true;
\r
621 if( document.addEventListener ){
\r
622 X_UA_EVENT.W3C = true;
\r
624 if( document.attachEvent ){
\r
625 X_UA_EVENT.IE = true;
\r
627 X_UA_EVENT.DOM0 = true;
\r
630 if( document.layers ){
\r
636 if( navigator.msPointerEnabled || navigator.pointerEnabled ) X_UA_HID.POINTER = true;
\r
637 if( !X_UA_HID.POINTER && window.ontouchstart !== undefined ) X_UA_HID.TOUCH = true;
\r
639 //alert(X_UA[ 'Safari' ] + ' ' + X_UA[ 'WebKit' ] + '\n\n' + navigator.userAgent + '\n\n' + navigator.appVersion + '\n\n' + navigator.platform );
\r
641 // Safari 3.1 未満は開発コンソールがない!
\r
642 // http://shimax.cocolog-nifty.com/search/2006/09/safarijavascrip_c54d.html
\r
644 if( X_UA[ 'Safari' ] && X_UA[ 'WebKit' ] < 525.13 ){
\r
645 window.onerror = function( x, y, z ){
\r
646 var n = String.fromCharCode( 10 );
\r
647 alert('window.onerrorによるエラーの捕捉:' + n + x + n + y + 'の' + z + '行目付近です。');
\r
652 // TODO 構文のサポート instanceof, in, try catch
\r
654 if( X_UA[ 'IE' ] < 7 ){ // error @ NN7.2
\r
655 X_UA[ 'IE4' ] || X_UA[ 'MacIE' ] ?
\r
656 document.execCommand && document.execCommand( 'BackgroundImageCache', false, true ) :
\r
659 * ie7 以下で実行する document.execCommand( 'BackgroundImageCache', false, true ) の失敗。
\r
660 * bonus: hotfix for IE6 SP1 (bug KB823727)
\r
661 * multipleIEs IE6 standalone 版では不可, IE5.5 は可,,,
\r
662 * @alias X.UA.ieExeComError */
\r
663 X_UA[ 'ieExeComError' ] = eval( 'var a=1;try{document.execCommand&&document.execCommand("BackgroundImageCache",!1,!0)}catch(e){a=0}!a' );
\r
666 X_UA[ 'ieExeComError' ] && alert( 'document.execCommand error!' );
\r
670 * HTML5 に対応しない IE8 以下でも <a> の下に <div> を作ることができる
\r
671 * その際に <div> の直前に改行文字が出現するが childNodes は長さ 1 で <div> だけの模様、、、
\r
672 X_UA_ATagWrapDiv = (function( e, h ){
\r
673 e = document.createElement( 'div' );
\r
674 e.innerHTML = h = '<a><div></div></a>';
\r
675 console.log( e.innerHTML.length + '\n' + e.firstChild.tagName );
\r
676 return e.childNodes.length === 1;
\r
679 console.log( 'HTML5? ' + X_UA_ATagWrapDiv ); */
\r