2 // ------------------------------------------------------------------------- //
\r
3 // ------------ local variables -------------------------------------------- //
\r
4 // ------------------------------------------------------------------------- //
\r
7 * UserAgent の関する定数を保持する。
\r
12 var X_UA = X[ 'UA' ] = {};
\r
15 var dua = n.userAgent,
\r
17 tv = parseFloat(dav),
\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 X_UA[ 'iPhone_4s' ] = true;
\r
73 * @alias X.UA.iPhone_3GS
\r
76 X_UA[ 'iPhone_3GS' ] = true;
\r
78 //alert( 'iPhone ' + ( X_UA[ 'iPhone_3GS' ] ? '3GS以下' : X_UA[ 'iPhone_4s' ] ? '4s以下' : '5以上' ) );
\r
80 if( sys === 'iPad' ){
\r
81 /** @memberof X.UA */
\r
82 X_UA[ 'iPad' ] = true;
\r
85 * iPad2以下または初代iPad mini 以下
\r
87 X_UA[ 'iPad_2Mini1' ] = true;
\r
90 if( sys === 'iPod' ){
\r
91 /** @memberof X.UA */
\r
92 X_UA[ 'iPod' ] = true;
\r
97 X_UA[ 'iPod_3' ] = true;
\r
102 * @memberof X.UA */
\r
103 X_UA[ 'iPod_4' ] = true;
\r
105 //alert( 'iPod touch ' + ( X_UA[ 'iPod_3' ] ? '3以下' : X_UA[ 'iPod_4' ] ? '4以下' : '5以上' ) );
\r
108 console.log( '>> iOS : ' + X_UA[ 'iOS' ] );
\r
110 if( dua.indexOf( 'hp-tablet' ) !== -1 || dua.indexOf( 'webOS' ) !== -1 ){
\r
111 // http://user-agent-string.info/list-of-ua/os-detail?os=webOS
\r
112 /** @memberof X.UA */
\r
113 X_UA[ 'webOS' ] = true; // webOS
\r
115 if( sys.indexOf( 'Win' ) + 1 ){
\r
116 console.log( 'Win' );
\r
117 /** @memberof X.UA */
\r
118 X_UA[ 'Windows' ] = true;
\r
124 X_UA[ sys ] = true;
\r
128 if( sys.indexOf( 'Mac' ) + 1 ){
\r
129 console.log( 'Mac' );
\r
130 /** @memberof X.UA */
\r
131 X_UA[ 'Mac' ] = true;
\r
133 case 'MacPowerPC' :
\r
134 /** @memberof X.UA */
\r
135 X_UA[ 'MacPPC' ] = true;
\r
140 X_UA[ sys ] = true;
\r
143 if( ( sys.indexOf( 'Linux' ) + 1 ) || ( sys.indexOf( 'Android' ) + 1 ) ){
\r
144 console.log( 'Linux' );
\r
145 /** @memberof X.UA */
\r
146 X_UA[ 'Linux' ] = true;
\r
148 if( ( i = dua.indexOf( 'Android' ) ) !== -1 ){
\r
149 /** @memberof X.UA */
\r
150 X_UA[ 'Android' ] = parseFloat( dua.substr( i + 8 ) ) || 0.1; // Firefox で Version が取れない!
\r
151 console.log( '>> Android : ' + X_UA[ 'Android' ] );
\r
156 * http://bizmakoto.jp/bizid/articles/1207/31/news004.html
\r
157 Chrome Android 4.0以上 Google
\r
158 Dolphin Browser HD Android 2.0.1以上 Mobotap
\r
159 Firefox Android 2.2以上 Mozilla
\r
160 Opera Mobile Android 1.6以上 Opera Software ASA
\r
161 Sleipnir Mobile Android 2.1以上 Fenrir
\r
164 if( window.opera ){
\r
165 i = dua.indexOf( 'Opera' ); // Opera/
\r
166 j = dua.indexOf( 'Version/' );
\r
167 /** @memberof X.UA */
\r
168 X_UA[ 'Opera' ] = v = Math.max(
\r
169 i !== -1 ? parseFloat( dua.substr( i + 6 ) ) : 0,
\r
170 j !== -1 ? parseFloat( dua.substr( j + 8 ) ) : 0,
\r
172 // closure compiler で minify するとOpera7で動かない
\r
173 // --compilation_level WHITESPACE_ONLY --formatting pretty_print <- 動く
\r
174 /** @memberof X.UA */
\r
175 X_UA[ 'Opera7' ] = v < 8;
\r
176 /** @memberof X.UA */
\r
177 X_UA[ 'Opera78' ] = v < 9;
\r
178 /** @memberof X.UA */
\r
179 X_UA[ 'OperaMini' ] = 0 < dua.indexOf('Opera Mini');
\r
180 /** @memberof X.UA */
\r
181 X_UA[ 'OperaMobile' ] = 0 < dua.indexOf('Opera Mobi');
\r
182 /** @memberof X.UA */
\r
183 X_UA[ 'OperaTablet' ] = 0 < dua.indexOf('Opera Tablet');
\r
184 /** @memberof X.UA */
\r
185 X_UA[ 'Wii' ] = dua.indexOf( 'Nintendo Wii' ) !== -1;
\r
186 /** @memberof X.UA */
\r
187 X_UA[ 'NDS' ] = dua.indexOf( 'Nitro' ) !== -1;
\r
188 console.log( '>> Opera : ' + v );
\r
192 // Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko
\r
193 if( document.all || dav.indexOf( 'Trident/' ) !== -1 ){
\r
194 /** @memberof X.UA */
\r
195 X_UA[ 'ActiveX' ] = !!window[ 'ActiveXObject' ];
\r
197 * documentモードを考慮しないIEのバージョン
\r
200 X_UA[ '_IE' ] = parseFloat(dua.split('MSIE ')[1]) || parseFloat(dua.split('rv:')[1]) || parseFloat(dav.split('MSIE ')[1]) || 0;
\r
201 // IE11 の互換モードの dav にも Trident/7.0 が書かれているため互換モードか?判定ができる
\r
202 // 互換モードでは Silverlight でエラーが出る?
\r
203 /** @memberof X.UA */
\r
204 X_UA[ 'Trident' ] = parseFloat(dav.split('Trident/')[1]) || 0;
\r
206 * documentモードを考慮したIEのバージョン
\r
207 * @memberof X.UA */
\r
208 X_UA[ 'IE' ] = v = document.documentMode || X_UA[ '_IE' ];
\r
209 tridentToVer = X_UA[ 'Trident' ] ? ( X_UA[ 'Trident' ] + 4 | 0 ) : X_UA[ '_IE' ];
\r
211 * IE11 の互換モードを使用しているか?
\r
212 * @memberof X.UA */
\r
213 X_UA[ 'IECompat' ] = /* v !== X_UA[ '_IE' ] || */ tridentToVer !== X_UA[ '_IE' ] && tridentToVer;
\r
214 /** @memberof X.UA */
\r
215 X_UA[ 'IE4' ] = v && v < 5;
\r
216 /** @memberof X.UA */
\r
217 X_UA[ 'IE5678' ] = 5 <= v && v < 9;
\r
218 /** @memberof X.UA */
\r
219 X_UA[ 'IE5' ] = 5 <= v && v < 5.5;
\r
220 /** @memberof X.UA */
\r
221 X_UA[ 'IE55' ] = 5.5 <= v && v < 6;
\r
222 /** @memberof X.UA */
\r
223 X_UA[ 'IE5x' ] = X_UA[ 'IE5' ] || X_UA[ 'IE55' ];
\r
224 /** @memberof X.UA */
\r
225 X_UA[ 'IE6' ] = 6 <= v && v < 7;
\r
226 /** @memberof X.UA */
\r
227 X_UA[ 'IE7' ] = 7 <= v && v < 8;
\r
228 /** @memberof X.UA */
\r
229 X_UA[ 'IE8' ] = 8 <= v && v < 9;
\r
230 /** @memberof X.UA */
\r
231 X_UA[ 'IE9' ] = 9 <= v && v < 10;
\r
232 /** @memberof X.UA */
\r
233 X_UA[ 'MacIE' ] = X_UA[ 'Mac' ];
\r
234 /** @memberof X.UA */
\r
235 X_UA[ 'IEMobile' ] = dua.toLowerCase().indexOf( 'iemobile' ) !== -1 || X_UA[ 'WinCE' ];
\r
236 /** @memberof X.UA */
\r
237 X_UA[ 'WinPhone' ] = dua.toLowerCase().indexOf( 'windows phone' ) !== -1 || 0 < dav.indexOf( 'ZuneWP' ); // ZuneWP は IEM のデスクトップモードで使用
\r
238 console.log( '>> IE : ' + v + ' ActiveX : ' + X_UA[ 'ActiveX' ] );
\r
239 // TODO XBox360, XBox1, Modern or Desktop, Standalone
\r
243 // http://qa.support.sony.jp/solution/S0812181056444/common/nfb34_dom_200jp/dom_dom0_JP.html
\r
244 if( ( i = dua.indexOf( 'NetFront\/' ) !== -1 ) ){
\r
245 /** @memberof X.UA */
\r
246 X_UA[ 'NetFront' ] = parseFloat( dua.substr( i + 9 ) ) || 0.1;
\r
247 console.log( '>> NetFront : ' + X_UA[ 'NetFront' ] );
\r
251 if( X_UA[ 'Linux' ] && tv === 2 && dua.indexOf( 'Sony\/COM2\/' ) !== -1 ){
\r
252 X_UA[ 'NetFront' ] = 3.4;
\r
253 console.log( '>> NetFront : ' + X_UA[ 'NetFront' ] );
\r
257 // http://www.useragentstring.com/pages/Playstation%203/
\r
258 // Mozilla/5.0 (PLAYSTATION 3; 3.55)
\r
259 // Mozilla/4.0 (PS3 (PlayStation 3); 1.00)
\r
260 // https://github.com/Famous/famous/blob/1a02c8084587d80519ea4bd3b55649ab32ee2e65/examples/assets/lib/require.js
\r
261 // PS3 ブラウザのロードイベントについて
\r
262 if( ( i = dua.toUpperCase().indexOf( 'PLAYSTATION 3' ) !== -1 ) ){
\r
264 * PlayStation 3 システムバージョン 4.10 未満の SONY 独自ブラウザ
\r
265 * @memberof X.UA */
\r
266 X_UA[ 'PS3' ] = parseFloat( dua.substr( i + 15 ) ) || 0.1;
\r
267 console.log( '>> PS3 : ' + X_UA[ 'PS3' ] );
\r
271 // http://www.useragentstring.com/pages/iCab/
\r
272 // iCab/3.0.2 (Macintosh; U; PPC Mac OS X)
\r
273 // Mozilla/5.0 (Macintosh; U; PPC Mac OS; en) iCab 3
\r
274 if( ( i = dua.indexOf( 'iCab' ) !== -1 ) ){
\r
275 /** @memberof X.UA */
\r
276 X_UA[ 'iCab' ] = parseFloat( dua.substr( i + 5 ) ) || 0.1;
\r
277 console.log( '>> iCab : ' + X_UA[ 'iCab' ] );
\r
281 if( 0 < dua.indexOf( 'Gecko\/' ) && ( i = dua.indexOf( 'rv:' ) ) ){
\r
282 v = dua.substr( i + 3 ).split( '.' );
\r
283 /** @memberof X.UA */
\r
284 X_UA[ 'Gecko' ] = parseFloat( v[ 0 ] ) || 0 +
\r
285 ( parseFloat( v[ 1 ] ) || 0 ) / 10 +
\r
286 ( parseFloat( v[ 2 ] ) || 0 ) / 100;
\r
287 /** @memberof X.UA */
\r
288 X_UA[ 'GeckoMajor' ] = parseFloat( v[ 0 ] ) || 0;
\r
289 /** @memberof X.UA */
\r
290 X_UA[ 'GeckoMinor' ] = parseFloat( v[ 1 ] ) || 0;
\r
291 /** @memberof X.UA */
\r
292 X_UA[ 'GeckoPatch' ] = parseFloat( v[ 2 ] ) || 0;
\r
295 // Mozilla/5.0 (Android; Linux armv7l; rv:9.0) Gecko/20111216 Firefox/9.0 Fennec/9.0
\r
296 if( ( i = dua.indexOf( 'Fennec/' ) ) !== -1 ){
\r
297 /** @memberof X.UA */
\r
298 X_UA[ 'Fennec' ] = parseFloat( dua.substr( i + 7 ) );
\r
299 console.log( '>> Fennec : ' + X_UA[ 'Fennec' ] + ', Gecko : ' + X_UA[ 'Gecko' ] );
\r
305 //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3
\r
306 if( ( i = dua.indexOf( 'Netscape6/' ) ) !== -1 ){
\r
307 /** @memberof X.UA */
\r
308 X_UA[ 'NN' ] = parseFloat( dua.substr( i + 10 ) ) || 6;
\r
309 /** @memberof X.UA */
\r
310 X_UA[ 'NN6' ] = true;
\r
311 console.log( '>> NN : ' + X_UA[ 'NN' ] + ', Gecko : ' + X_UA[ 'Gecko' ] );
\r
314 //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)
\r
315 //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20070321 Netscape/8.1.3
\r
316 if( ( i = dua.indexOf( 'Netscape/' ) ) !== -1 ){
\r
317 X_UA[ 'NN' ] = parseFloat( dua.substr( i + 9 ) ) || 7;
\r
318 console.log( '>> NN : ' + X_UA[ 'NN' ] + ', Gecko : ' + X_UA[ 'Gecko' ] );
\r
321 //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
322 if( ( i = dua.indexOf( 'Navigator/' ) ) !== -1 ){
\r
323 X_UA[ 'NN' ] = parseFloat( dua.substr( i + 10 ) ) || 9;
\r
324 console.log( '>> NN : ' + X_UA[ 'NN' ] + ', Gecko : ' + X_UA[ 'Gecko' ] );
\r
328 console.log( '>> Gecko : ' + X_UA[ 'Gecko' ] );
\r
332 if( window.chrome ){
\r
333 /** @memberof X.UA */
\r
334 X_UA[ 'Blink' ] = tv;
\r
335 console.log( '>>Blink : ' + X_UA[ 'Blink' ] );
\r
338 if( dav.indexOf( 'Konqueror' ) !== -1 ){
\r
339 /** @memberof X.UA */
\r
340 X_UA[ 'Khtml' ] = tv;
\r
341 console.log( '>>Khtml : ' + X_UA[ 'Khtml' ] );
\r
344 if( ( i = dua.indexOf( 'Android ' ) ) !== -1 ){
\r
345 /** @memberof X.UA */
\r
346 X_UA[ 'AndroidBrowser' ] = i = parseFloat( dua.substr( i + 8 ) ) || 0.1;
\r
347 /** @memberof X.UA */
\r
348 X_UA[ 'AndroidBrowser1' ] = 1 <= i && i < 2;
\r
349 /** @memberof X.UA */
\r
350 X_UA[ 'AndroidBrowser2' ] = 2 <= i && i < 3;
\r
351 /** @memberof X.UA */
\r
352 X_UA[ 'AndroidBrowser3' ] = 3 <= i && i < 4;
\r
353 /** @memberof X.UA */
\r
354 X_UA[ 'AndroidBrowser4' ] = 4 <= i && i < 5;
\r
355 /** @memberof X.UA */
\r
356 X_UA[ 'AndroidBrowser5' ] = 5 <= i && i < 6;
\r
357 console.log( '>> AndroidBrowser : ' + X_UA[ 'Android' ] );
\r
359 i = parseFloat(dua.split('WebKit\/')[1]);
\r
360 /** @memberof X.UA */
\r
361 X_UA[ 'AndroidBrowserWebkit' ] = i;
\r
362 alert( 'AudioSprite調査:Android標準ブラウザ Webkit Version ' + i );
\r
365 if( i = parseFloat(dua.split('WebKit\/')[1]) ){
\r
366 /** @memberof X.UA */
\r
367 X_UA[ 'WebKit' ] = i;
\r
369 if( v = parseFloat(dua.split('Chrome\/')[1]) ){
\r
370 /** @memberof X.UA */
\r
371 X_UA[ 'Chrome' ] = v;
\r
374 // TODO webkit Opera
\r
376 console.log( '>>Webkit : ' + X_UA[ 'WebKit' ] );
\r
378 if( i && !X_UA[ 'Chrome' ] && dua.indexOf( 'Safari' ) !== -1 ){
\r
379 if( dav.indexOf( 'Version/' ) !== -1 ){
\r
380 /** @memberof X.UA */
\r
381 X_UA[ 'Safari' ] = parseFloat( dav.split('Version/')[1] );
\r
384 X_UA[ 'Safari' ] = i < 73 ? 0.8 :
\r
392 i <= 525.25 ? 3.1 : 3.2;
\r
397 console.log( '>> Webkit : ' + X_UA[ 'WebKit' ] + ' Safari : ' + X_UA[ 'Safari' ] );
\r
400 //http://www.useragentstring.com/pages/Iris/
\r
401 if( dua.toLowerCase().indexOf( 'iris' ) !== -1 ) X_UA[ 'Iris' ] = true;
\r
403 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
404 dua.indexOf( 'Kobo' ) !== -1 ||
\r
405 // 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
406 dua.indexOf( 'Kindle' ) !== -1 ||
\r
407 // 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
408 dua.indexOf( 'EBRD' ) !== -1
\r
410 /** @memberof X.UA */
\r
411 X_UA[ 'EInk' ] = true;
\r
418 //X_UA[ 'IECompat' ] && alert( X_UA[ 'IE' ] + ' ' + X_UA[ '_IE' ] + ' Tri:' + X_UA[ 'Trident' ] );
\r
421 * http://d.hatena.ne.jp/t-uchima/20051003/p1
\r
422 * MacIEにはattachEventが一応あるけどwindow.attachEventとdocument.attachEventしかなく他の要素にはattachEventはない。
\r
424 if( X_UA[ 'IE4' ] && X_UA[ 'IE' ] < 5 ){ // ie4 & iemobi4 & macie4.x
\r
425 X_UA_DOM.IE4 = true;
\r
426 X_UA_EVENT.IE4 = true;
\r
428 if( X_UA[ 'MacIE' ] ){
\r
429 X_UA_DOM.W3C = true;
\r
430 X_UA_EVENT.IE = true;
\r
432 if( document.getElementById ){
\r
433 X_UA_DOM.W3C = true;
\r
434 if( document.addEventListener ){
\r
435 X_UA_EVENT.W3C = true;
\r
437 if( document.attachEvent ){
\r
438 X_UA_EVENT.IE = true;
\r
440 X_UA_EVENT.DOM0 = true;
\r
443 if( document.layers ){
\r
449 if( navigator.msPointerEnabled || navigator.pointerEnabled ) X_UA_HID.POINTER = true;
\r
450 if( !X_UA_HID.POINTER && window.ontouchstart !== undefined ) X_UA_HID.TOUCH = true;
\r
452 //alert(X_UA[ 'Safari' ] + ' ' + X_UA[ 'WebKit' ] + '\n\n' + navigator.userAgent + '\n\n' + navigator.appVersion + '\n\n' + navigator.platform );
\r
454 // Safari 3.1 未満は開発コンソールがない!
\r
455 // http://shimax.cocolog-nifty.com/search/2006/09/safarijavascrip_c54d.html
\r
457 if( X_UA[ 'Safari' ] && X_UA[ 'WebKit' ] < 525.13 ){
\r
458 window.onerror = function( x, y, z ){
\r
459 var n = String.fromCharCode( 10 );
\r
460 alert('window.onerrorによるエラーの捕捉:' + n + x + n + y + 'の' + z + '行目付近です。');
\r
465 // TODO 構文のサポート instanceof, in, try catch
\r
467 if( X_UA[ 'IE' ] < 7 ){ // error @ NN7.2
\r
468 X_UA[ 'IE4' ] || X_UA[ 'MacIE' ] ?
\r
469 document.execCommand && document.execCommand( 'BackgroundImageCache', false, true ) :
\r
472 * ie7 以下で実行する document.execCommand( 'BackgroundImageCache', false, true ) の失敗。
\r
473 * bonus: hotfix for IE6 SP1 (bug KB823727)
\r
474 * multipleIEs IE6 standalone 版では不可, IE5.5 は可,,,
\r
475 * @memberof X.UA */
\r
476 X_UA[ 'ieExeComError' ] = eval( 'var a=1;try{document.execCommand&&document.execCommand("BackgroundImageCache",!1,!0)}catch(e){a=0}!a' );
\r
479 X_UA[ 'ieExeComError' ] && alert( 'document.execCommand error!' );
\r
483 * HTML5 に対応しない IE8 以下でも <a> の下に <div> を作ることができる
\r
484 * その際に <div> の直前に改行文字が出現するが childNodes は長さ 1 で <div> だけの模様、、、
\r
485 X_UA_ATagWrapDiv = (function( e, h ){
\r
486 e = document.createElement( 'div' );
\r
487 e.innerHTML = h = '<a><div></div></a>';
\r
488 console.log( e.innerHTML.length + '\n' + e.firstChild.tagName );
\r
489 return e.childNodes.length === 1;
\r
492 console.log( 'HTML5? ' + X_UA_ATagWrapDiv ); */
\r