2 // ------------------------------------------------------------------------- //
\r
3 // ------------ local variables -------------------------------------------- //
\r
4 // ------------------------------------------------------------------------- //
\r
5 var X_UA = (function( n, undefined ){
\r
11 tv = parseFloat(dav),
\r
13 tridentToVer, i, j, v;
\r
15 console.log( ' userAgent : ' + dua );
\r
17 console.log( ' appVersion : ' + dav );
\r
19 console.log( ' platform : ' + sys );
\r
22 // TODO 3DS, DSi, WiiU
\r
24 if( sys.indexOf( 'iP' ) === 0 ){
\r
26 v = dua.split( 'OS ' )[ 1 ].split( '_' );
\r
27 i = window.devicePixelRatio === 1;
\r
28 /** @memberof X.UA */
\r
29 acme.iOSMajor = parseFloat( v[ 0 ] ) || 0;
\r
30 /** @memberof X.UA */
\r
31 acme.iOSMinor = parseFloat( v[ 1 ] ) || 0;
\r
32 /** @memberof X.UA */
\r
33 acme.iOSPatch = parseFloat( v[ 2 ] ) || 0;
\r
34 /** @memberof X.UA */
\r
35 acme.iOS = acme.iOSMajor + acme.iOSMinor / 10;
\r
37 if( screen.width === screen.height * 1.5 || screen.width * 1.5 === screen.height ){
\r
38 v = true; // 4:3 model
\r
41 if( sys === 'iPhone' ){
\r
42 /** @memberof X.UA */
\r
47 acme.iPhone_4s = true;
\r
52 acme.iPhone_3GS = true;
\r
54 //alert( 'iPhone ' + ( acme.iPhone_3GS ? '3GS以下' : acme.iPhone_4s ? '4s以下' : '5以上' ) );
\r
56 if( sys === 'iPad' ){
\r
57 /** @memberof X.UA */
\r
61 * iPad2以下または初代iPad mini 以下
\r
63 acme.iPad_2Mini1 = true;
\r
66 if( sys === 'iPod' ){
\r
67 /** @memberof X.UA */
\r
81 //alert( 'iPod touch ' + ( acme.iPod_3 ? '3以下' : acme.iPod_4 ? '4以下' : '5以上' ) );
\r
84 console.log( '>> iOS : ' + acme.iOS );
\r
86 if( dua.indexOf( 'hp-tablet' ) !== -1 || dua.indexOf( 'webOS' ) !== -1 ){
\r
87 // http://user-agent-string.info/list-of-ua/os-detail?os=webOS
\r
88 /** @memberof X.UA */
\r
89 acme.webOS = true; // webOS
\r
91 if( sys.indexOf( 'Win' ) + 1 ){
\r
92 console.log( 'Win' );
\r
93 /** @memberof X.UA */
\r
94 acme.Windows = true;
\r
100 acme[ sys ] = true;
\r
104 if( sys.indexOf( 'Mac' ) + 1 ){
\r
105 console.log( 'Mac' );
\r
106 /** @memberof X.UA */
\r
109 case 'MacPowerPC' :
\r
110 /** @memberof X.UA */
\r
111 acme.MacPPC = true;
\r
119 if( ( sys.indexOf( 'Linux' ) + 1 ) || ( sys.indexOf( 'Android' ) + 1 ) ){
\r
120 console.log( 'Linux' );
\r
121 /** @memberof X.UA */
\r
124 if( ( i = dua.indexOf( 'Android' ) ) !== -1 ){
\r
125 /** @memberof X.UA */
\r
126 acme.Android = parseFloat( dua.substr( i + 8 ) ) || 0.1; // Firefox で Version が取れない!
\r
127 console.log( '>> Android : ' + acme.Android );
\r
132 * http://bizmakoto.jp/bizid/articles/1207/31/news004.html
\r
133 Chrome Android 4.0以上 Google
\r
134 Dolphin Browser HD Android 2.0.1以上 Mobotap
\r
135 Firefox Android 2.2以上 Mozilla
\r
136 Opera Mobile Android 1.6以上 Opera Software ASA
\r
137 Sleipnir Mobile Android 2.1以上 Fenrir
\r
140 if( window.opera ){
\r
141 i = dua.indexOf( 'Opera' ); // Opera/
\r
142 j = dua.indexOf( 'Version/' );
\r
143 /** @memberof X.UA */
\r
144 acme.Opera = Math.max(
\r
145 i !== -1 ? parseFloat( dua.substr( i + 6 ) ) : 0,
\r
146 j !== -1 ? parseFloat( dua.substr( j + 8 ) ) : 0,
\r
148 // closure compiler で minify するとOpera7で動かない
\r
149 // --compilation_level WHITESPACE_ONLY --formatting pretty_print <- 動く
\r
150 /** @memberof X.UA */
\r
151 acme.Opera7 = acme.Opera < 8;
\r
152 /** @memberof X.UA */
\r
153 acme.Opera78 = acme.Opera < 9;
\r
154 /** @memberof X.UA */
\r
155 acme.OperaMini = 0 < dua.indexOf('Opera Mini');
\r
156 /** @memberof X.UA */
\r
157 acme.OperaMobile = 0 < dua.indexOf('Opera Mobi');
\r
158 /** @memberof X.UA */
\r
159 acme.OperaTablet = 0 < dua.indexOf('Opera Tablet');
\r
160 /** @memberof X.UA */
\r
161 acme.Wii = dua.indexOf( 'Nintendo Wii' ) !== -1;
\r
162 /** @memberof X.UA */
\r
163 acme.NDS = dua.indexOf( 'Nitro' ) !== -1;
\r
164 console.log( '>> Opera : ' + acme.Opera );
\r
168 // Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko
\r
169 if( document.all || dav.indexOf( 'Trident/' ) !== -1 ){
\r
170 /** @memberof X.UA */
\r
171 acme.ActiveX = !!window[ 'ActiveXObject' ];
\r
173 * documentモードを考慮しないIEのバージョン
\r
176 acme._IE = parseFloat(dua.split('MSIE ')[1]) || parseFloat(dua.split('rv:')[1]) || parseFloat(dav.split('MSIE ')[1]) || 0;
\r
177 // IE11 の互換モードの dav にも Trident/7.0 が書かれているため互換モードか?判定ができる
\r
178 // 互換モードでは Silverlight でエラーが出る?
\r
179 /** @memberof X.UA */
\r
180 acme.Trident = parseFloat(dav.split('Trident/')[1]) || 0;
\r
182 * documentモードを考慮したIEのバージョン
\r
183 * @memberof X.UA */
\r
184 acme.IE = document.documentMode || acme._IE;
\r
185 tridentToVer = acme.Trident ? ( acme.Trident + 4 | 0 ) : acme._IE;
\r
187 * IE11 の互換モードを使用しているか?
\r
188 * @memberof X.UA */
\r
189 acme.IECompat = /* acme.IE !== acme._IE || */ tridentToVer !== acme._IE && tridentToVer;
\r
190 /** @memberof X.UA */
\r
191 acme.IE4 = acme.IE && acme.IE < 5;
\r
192 /** @memberof X.UA */
\r
193 acme.IE5678 = 5 <= acme.IE && acme.IE < 9;
\r
194 /** @memberof X.UA */
\r
195 acme.IE5 = 5 <= acme.IE && acme.IE < 5.5;
\r
196 /** @memberof X.UA */
\r
197 acme.IE55 = 5.5 <= acme.IE && acme.IE < 6;
\r
198 /** @memberof X.UA */
\r
199 acme.IE5x = acme.IE5 || acme.IE55;
\r
200 /** @memberof X.UA */
\r
201 acme.IE6 = 6 <= acme.IE && acme.IE < 7;
\r
202 /** @memberof X.UA */
\r
203 acme.IE7 = 7 <= acme.IE && acme.IE < 8;
\r
204 /** @memberof X.UA */
\r
205 acme.IE8 = 8 <= acme.IE && acme.IE < 9;
\r
206 /** @memberof X.UA */
\r
207 acme.IE9 = 9 <= acme.IE && acme.IE < 10;
\r
208 /** @memberof X.UA */
\r
209 acme.MacIE = acme.Mac;
\r
210 /** @memberof X.UA */
\r
211 acme.IEMobile = dua.toLowerCase().indexOf( 'iemobile' ) !== -1 || acme.WinCE;
\r
212 /** @memberof X.UA */
\r
213 acme.WinPhone = dua.toLowerCase().indexOf( 'windows phone' ) !== -1 || 0 < dav.indexOf( 'ZuneWP' ); // ZuneWP は IEM のデスクトップモードで使用
\r
214 console.log( '>> IE : ' + acme.IE + ' ActiveX : ' + acme.ActiveX );
\r
215 // TODO XBox360, XBox1, Modern or Desktop, Standalone
\r
219 // http://qa.support.sony.jp/solution/S0812181056444/common/nfb34_dom_200jp/dom_dom0_JP.html
\r
220 if( ( i = dua.indexOf( 'NetFront\/' ) !== -1 ) ){
\r
221 /** @memberof X.UA */
\r
222 acme.NetFront = parseFloat( dua.substr( i + 9 ) ) || 0.1;
\r
223 console.log( '>> NetFront : ' + acme.NetFront );
\r
227 if( acme.Linux && tv === 2 && dua.indexOf( 'Sony\/COM2\/' ) !== -1 ){
\r
228 acme.NetFront = 3.4;
\r
229 console.log( '>> NetFront : ' + acme.NetFront );
\r
233 // http://www.useragentstring.com/pages/Playstation%203/
\r
234 // Mozilla/5.0 (PLAYSTATION 3; 3.55)
\r
235 // Mozilla/4.0 (PS3 (PlayStation 3); 1.00)
\r
236 // https://github.com/Famous/famous/blob/1a02c8084587d80519ea4bd3b55649ab32ee2e65/examples/assets/lib/require.js
\r
237 // PS3 ブラウザのロードイベントについて
\r
238 if( ( i = dua.toUpperCase().indexOf( 'PLAYSTATION 3' ) !== -1 ) ){
\r
240 * PlayStation 3 システムバージョン 4.10 未満の SONY 独自ブラウザ
\r
241 * @memberof X.UA */
\r
242 acme.PS3 = parseFloat( dua.substr( i + 15 ) ) || 0.1;
\r
243 console.log( '>> PS3 : ' + acme.PS3 );
\r
247 // http://www.useragentstring.com/pages/iCab/
\r
248 // iCab/3.0.2 (Macintosh; U; PPC Mac OS X)
\r
249 // Mozilla/5.0 (Macintosh; U; PPC Mac OS; en) iCab 3
\r
250 if( ( i = dua.indexOf( 'iCab' ) !== -1 ) ){
\r
251 /** @memberof X.UA */
\r
252 acme.iCab = parseFloat( dua.substr( i + 5 ) ) || 0.1;
\r
253 console.log( '>> iCab : ' + acme.iCab );
\r
257 if( 0 < dua.indexOf( 'Gecko\/' ) && ( i = dua.indexOf( 'rv:' ) ) ){
\r
258 v = dua.substr( i + 3 ).split( '.' );
\r
259 /** @memberof X.UA */
\r
260 acme.Gecko = parseFloat( v[ 0 ] ) || 0 +
\r
261 ( parseFloat( v[ 1 ] ) || 0 ) / 10 +
\r
262 ( parseFloat( v[ 2 ] ) || 0 ) / 100;
\r
263 /** @memberof X.UA */
\r
264 acme.GeckoMajor = parseFloat( v[ 0 ] ) || 0;
\r
265 /** @memberof X.UA */
\r
266 acme.GeckoMinor = parseFloat( v[ 1 ] ) || 0;
\r
267 /** @memberof X.UA */
\r
268 acme.GeckoPatch = parseFloat( v[ 2 ] ) || 0;
\r
271 // Mozilla/5.0 (Android; Linux armv7l; rv:9.0) Gecko/20111216 Firefox/9.0 Fennec/9.0
\r
272 if( ( i = dua.indexOf( 'Fennec/' ) ) !== -1 ){
\r
273 /** @memberof X.UA */
\r
274 acme.Fennec = parseFloat( dua.substr( i + 7 ) );
\r
275 console.log( '>> Fennec : ' + acme.Fennec + ', Gecko : ' + acme.Gecko );
\r
281 //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4.1) Gecko/20020508 Netscape6/6.2.3
\r
282 if( ( i = dua.indexOf( 'Netscape6/' ) ) !== -1 ){
\r
283 /** @memberof X.UA */
\r
284 acme.NN = parseFloat( dua.substr( i + 10 ) ) || 6;
\r
285 /** @memberof X.UA */
\r
287 console.log( '>> NN : ' + acme.NN + ', Gecko : ' + acme.Gecko );
\r
290 //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)
\r
291 //Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20070321 Netscape/8.1.3
\r
292 if( ( i = dua.indexOf( 'Netscape/' ) ) !== -1 ){
\r
293 acme.NN = parseFloat( dua.substr( i + 9 ) ) || 7;
\r
294 console.log( '>> NN : ' + acme.NN + ', Gecko : ' + acme.Gecko );
\r
297 //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
298 if( ( i = dua.indexOf( 'Navigator/' ) ) !== -1 ){
\r
299 acme.NN = parseFloat( dua.substr( i + 10 ) ) || 9;
\r
300 console.log( '>> NN : ' + acme.NN + ', Gecko : ' + acme.Gecko );
\r
304 console.log( '>> Gecko : ' + acme.Gecko );
\r
308 if( window.chrome ){
\r
309 /** @memberof X.UA */
\r
311 console.log( '>>Blink : ' + acme.Blink );
\r
314 if( dav.indexOf( 'Konqueror' ) !== -1 ){
\r
315 /** @memberof X.UA */
\r
317 console.log( '>>Khtml : ' + acme.Khtml );
\r
320 if( ( i = dua.indexOf( 'Android ' ) ) !== -1 ){
\r
321 /** @memberof X.UA */
\r
322 acme.AndroidBrowser = i = parseFloat( dua.substr( i + 8 ) ) || 0.1;
\r
323 /** @memberof X.UA */
\r
324 acme.AndroidBrowser1 = 1 <= i && i < 2;
\r
325 /** @memberof X.UA */
\r
326 acme.AndroidBrowser2 = 2 <= i && i < 3;
\r
327 /** @memberof X.UA */
\r
328 acme.AndroidBrowser3 = 3 <= i && i < 4;
\r
329 /** @memberof X.UA */
\r
330 acme.AndroidBrowser4 = 4 <= i && i < 5;
\r
331 /** @memberof X.UA */
\r
332 acme.AndroidBrowser5 = 5 <= i && i < 6;
\r
333 console.log( '>> AndroidBrowser : ' + acme.Android );
\r
335 i = parseFloat(dua.split('WebKit\/')[1]);
\r
336 /** @memberof X.UA */
\r
337 acme.AndroidBrowserWebkit = i;
\r
338 alert( 'AudioSprite調査:Android標準ブラウザ Webkit Version ' + i );
\r
341 if( i = parseFloat(dua.split('WebKit\/')[1]) ){
\r
342 /** @memberof X.UA */
\r
344 /** @memberof X.UA */
\r
345 acme.Chrome = parseFloat(dua.split('Chrome\/')[1]) || undefined;
\r
347 // TODO webkit Opera
\r
349 console.log( '>>Webkit : ' + acme.WebKit );
\r
351 if( i && !acme.Chrome && dua.indexOf( 'Safari' ) !== -1 ){
\r
352 if( dav.indexOf( 'Version/' ) !== -1 ){
\r
353 /** @memberof X.UA */
\r
354 acme.Safari = parseFloat( dav.split('Version/')[1] );
\r
389 console.log( '>> Webkit : ' + acme.WebKit + ' Safari : ' + acme.Safari );
\r
392 //http://www.useragentstring.com/pages/Iris/
\r
393 if( dua.toLowerCase().indexOf( 'iris' ) !== -1 ) acme.Iris = true;
\r
395 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
396 dua.indexOf( 'Kobo' ) !== -1 ||
\r
397 // 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
398 dua.indexOf( 'Kindle' ) !== -1 ||
\r
399 // 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
400 dua.indexOf( 'EBRD' ) !== -1
\r
402 /** @memberof X.UA */
\r
411 //X_UA.IECompat && alert( X_UA.IE + ' ' + X_UA._IE + ' Tri:' + X_UA.Trident );
\r
414 * http://d.hatena.ne.jp/t-uchima/20051003/p1
\r
415 * MacIEにはattachEventが一応あるけどwindow.attachEventとdocument.attachEventしかなく他の要素にはattachEventはない。
\r
417 if( X_UA.IE4 && X_UA.IE < 5 ){ // ie4 & iemobi4 & macie4.x
\r
418 X_UA_DOM.IE4 = true;
\r
419 X_UA_EVENT.IE4 = true;
\r
422 X_UA_DOM.W3C = true;
\r
423 X_UA_EVENT.IE = true;
\r
425 if( document.getElementById ){
\r
426 X_UA_DOM.W3C = true;
\r
427 if( document.addEventListener ){
\r
428 X_UA_EVENT.W3C = true;
\r
430 if( document.attachEvent ){
\r
431 X_UA_EVENT.IE = true;
\r
433 X_UA_EVENT.DOM0 = true;
\r
436 if( document.layers ){
\r
442 if( navigator.msPointerEnabled || navigator.pointerEnabled ) X_UA_HID.POINTER = true;
\r
443 if( !X_UA_HID.POINTER && window.ontouchstart !== undefined ) X_UA_HID.TOUCH = true;
\r
445 //alert(X_UA.Safari + ' ' + X_UA.WebKit + '\n\n' + navigator.userAgent + '\n\n' + navigator.appVersion + '\n\n' + navigator.platform );
\r
447 // Safari 3.1 未満は開発コンソールがない!
\r
448 // http://shimax.cocolog-nifty.com/search/2006/09/safarijavascrip_c54d.html
\r
450 if( X_UA.Safari && X_UA.WebKit < 525.13 ){
\r
451 window.onerror = function( x, y, z ){
\r
452 var n = String.fromCharCode( 10 );
\r
453 alert('window.onerrorによるエラーの捕捉:' + n + x + n + y + 'の' + z + '行目付近です。');
\r
458 // ------------------------------------------------------------------------- //
\r
459 // --- interface ----------------------------------------------------------- //
\r
460 // ------------------------------------------------------------------------- //
\r
463 * UserAgent の関する定数を保持する。
\r
470 // TODO 構文のサポート instanceof, in, try catch
\r
472 if( X_UA.IE < 7 ){ // error @ NN7.2
\r
473 // bonus: hotfix for IE6 SP1 (bug KB823727)
\r
474 // multipleIEs IE6 standalone 版では不可, IE5.5 は可,,,
\r
475 X_UA.IE4 || X_UA.MacIE ?
\r
476 document.execCommand && document.execCommand( 'BackgroundImageCache', false, true ) :
\r
478 X_UA.IE_EXECOM_ERROR = eval( 'var a=1;try{document.execCommand&&document.execCommand("BackgroundImageCache",!1,!0)}catch(e){a=0}!a' );
\r
481 X_UA.IE_EXECOM_ERROR && alert( 'document.execCommand error!' );
\r
485 * HTML5 に対応しない IE8 以下でも <a> の下に <div> を作ることができる
\r
486 * その際に <div> の直前に改行文字が出現するが childNodes は長さ 1 で <div> だけの模様、、、
\r
487 X_UA_ATagWrapDiv = (function( e, h ){
\r
488 e = document.createElement( 'div' );
\r
489 e.innerHTML = h = '<a><div></div></a>';
\r
490 console.log( e.innerHTML.length + '\n' + e.firstChild.tagName );
\r
491 return e.childNodes.length === 1;
\r
494 console.log( 'HTML5? ' + X_UA_ATagWrapDiv ); */
\r