chicago
Version:
A front-end JavaScript library for user-interface developers.
586 lines (541 loc) • 16.7 kB
JavaScript
/*!
* Chicago - Browser
* A collection of browser capability methods
*
* Copyright (c) 2015 Erik Nielsen
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* https://nielse63.github.io/Chicago/
*
* Version: @VERSION
*
*/
(function( global, factory ) {
var module;
var Chicago = global.Chicago || null;
if(Chicago) {
module = factory( Chicago, global, global.document );
}
if( typeof define === 'function' && define.amd ) {
define('chicago-browser', ['chicago'], function() {
return module || factory( Chicago, global, global.document );
});
}
})(typeof window !== "undefined" ? window : (typeof this.window !== "undefined" ? this.window : this), function( _c, win, doc ) {
var test = function( rgx ) {
var ua = win.navigator.userAgent;
return rgx.test( ua ) || rgx.test( ua.toLowerCase() );
};
var exec = function( rgx ) {
var ua = win.navigator.userAgent;
return rgx.exec( ua ) || rgx.exec( ua.toLowerCase() );
};
var uamatches = function( key ) {
var ua = win.navigator.userAgent;
return ua.indexOf( key ) > -1 || ua.toLowerCase().indexOf( key ) > -1;
};
var match = function( key ) {
var matches = win.navigator.userAgent.match(key);
return !! matches ? matches[0] : null;
};
var version = function(obj, string) {
var returnObj = {
version : {
full : string
}
};
var versionArray = string.split('.');
if(versionArray.length > 0) {
versionArray = versionArray.reverse();
returnObj.version.major = parseFloat( versionArray.pop() );
if(versionArray.length > 0) {
returnObj.version.minor = parseFloat( versionArray.pop() );
if(versionArray.length > 0) {
versionArray = versionArray.reverse();
returnObj.version.patch = parseFloat( versionArray.join('.') );
} else {
returnObj.version.patch = 0;
}
} else {
returnObj.version.minor = 0;
}
} else {
returnObj.version.major = 0;
}
return _c.$.extend( obj, returnObj );
};
var objectHasKey = function( search, obj ) {
if( ! _c.utils.is.object( obj ) ) {
return false;
}
if( _c.utils.is.string( search ) ) {
search = search.toLowerCase();
}
for( var k in obj ) {
var val = obj[k];
if( _c.utils.is.string( val ) ) {
val = val.toLowerCase();
}
if( _c.utils.is.object( val ) ) {
var contains = objectHasKey( search, val );
if( contains ) {
return true;
}
}
if( val === search ) {
return true;
}
}
return false;
};
var defs = {
device : {
types : ['TV', 'Tablet', 'Mobile', 'Desktop'],
},
screens : {
mini : 0,
small : 480,
medium : 768,
large : 960,
xlarge : 1220
},
};
_c.browser = {
is : function( string ) {
return objectHasKey( string, this );
},
can : function( style ) {
var supports = (function() {
var div = doc.createElement('div');
var vendors = 'Khtml Ms ms O Moz Webkit'.split(' ');
return function(prop) {
if( ! _c.utils.is.undefined( div.style[prop] ) ) {
return true;
}
prop = prop.replace(/^[a-z]/, function(val) {
return val.toUpperCase();
});
for(var i = 0; i < vendors.length; i++) {
var vendor = vendors[i];
if( ! _c.utils.is.undefined( div.style[vendor + prop] ) ) {
return true;
}
}
return false;
};
})();
return supports( style );
},
getPrefix : function( prop ) {
var div = doc.createElement( 'div' ),
vendors = 'Khtml Ms ms O Moz Webkit'.split(' ');
prop = _c.utils.toCamelCase( prop );
if( ! _c.utils.is.undefined( div.style[prop] ) ) {
return '';
}
for( var i = 0; i < vendors.length; i++ ) {
var vendor = vendors[i];
if( ! _c.utils.is.undefined( div.style[vendor + prop] ) ) {
return '-' + vendor.toLowerCase() + '-';
}
}
return '';
},
};
return _c.module('browserProxy', {
defaults : {
check : {
borwser : true,
device : true,
language : true,
os : true,
plugins : true,
screen : true,
touch : true,
},
addHTMLClasses : true,
},
classes : [],
boot : function() {
return _c.ready(function() {
var ele = _c.$doc;
if( ! ele.data( 'chicago.data.browserProxy' ) ) {
_c.browserProxy( ele );
}
});
},
init : function() {
_c.$doc.on('ready.chicago.dom reloaded.chicago.dom', function(_this) {
return function(e) {
_this.setBrowserData();
};
}(this));
},
// setters
setBrowserData : function() {
if( this.options.check.touch ) {
_c.browser.touch = this.getTouch();
}
if( this.options.check.device ) {
_c.browser.device = this.getDevice();
}
if( this.options.check.screen ) {
_c.browser.screen = this.getScreen();
}
if( this.options.check.os ) {
_c.browser.os = this.getOS();
}
if( this.options.check.borwser ) {
_c.browser.browser = this.getBrowser();
}
if( this.options.check.language ) {
_c.browser.language = this.getLanguage();
}
if( this.options.check.plugins ) {
_c.browser.plugins = this.getPlugins();
}
if( this.options.addHTMLClasses ) {
this.addHTMLClasses();
}
win.setTimeout(function() {
_c.$doc.trigger('updated.chicago.browser');
});
},
// getters
getTouch : function() {
var touch = 'ontouchstart' in win && win.navigator.userAgent.toLowerCase().match(/mobile|tablet/) ||
win.DocumentTouch && doc instanceof win.DocumentTouch ||
win.navigator.msPointerEnabled && win.navigator.msMaxTouchPoints > 0 ||
win.navigator.pointerEnabled && win.navigator.maxTouchPoints > 0 ||
false;
return !! touch;
},
getDevice : function() {
var device = {
type : null,
model : null
};
if( test(/GoogleTV|SmartTV|SMART-TV|Internet.TV|NetCast|NetTV|AppleTV|Boxee|Kylo|Roku|dlnadoc|Roku|POV_TV|HbbTV|ce\-html/) ) {
device.type = defs.device.types[0];
device.model = 'SmartTV';
} else if( test(/Xbox|PLAYSTATION 3|Wii/) ) {
device.type = defs.device.types[0];
device.model = 'Game Console';
} else if( test(/ip(a|ro)d/)) {
device.type = defs.device.types[1];
device.model = 'iPad';
} else if( ( test(/tablet/) && ! test(/rx-34/) ) || test(/folio/) ) {
device.type = defs.device.types[1];
device.model = String( exec(/PlayBook/) || '' );
} else if( test(/linux/) && test(/Android/) && ! test(/Fennec|mobi|htc.magic|htcX06ht|nexus.one|sc-02b|fone.945/) ) {
device.type = defs.device.types[1];
device.model = 'Android';
} else if( test(/Kindle/) || ( test(/mac.os/) && test(/silk/)) ) {
device.type = defs.device.types[1];
device.model = 'Kindle';
} else if( test(/gt-p10|sc-01c|shw-m180s|sgh-t849|sch-i800|shw-m180l|sph-p100|sgh-i987|zt180|htc(.flyer|\_flyer)|sprint.atp51|viewpad7|pandigital(sprnova|nova)|ideos.s7|dell.streak.7|advent.vega|a101it|a70bht|mid7015|next2|nook/) || ( test(/mb511/) && test(/rutem/))) {
device.type = defs.device.types[1];
device.model = 'Android';
} else if( test(/bb10/)) {
device.type = defs.device.types[1];
device.model = 'BlackBerry';
} else {
device.model = exec(/iPhone|iPod|Android|BlackBerry|Opera Mini|Opera Mobi|Skyfire|Maemo|Windows Phone|Palm|IEMobile|Symbian|SymbianOS|Fennec|J2ME/);
if(device.model !== null) {
device.type = defs.device.types[2];
device.model = match( String( device.model ) );
} else {
device.model = '';
if( test(/Bolt|Fennec|Iris|Maemo|minimo|mobi|mowser|netfront|novarra|prism|rx-34|Skyfire|tear|xv6875|xv6975|google.wireless.transcoder/)) {
device.type = defs.device.types[2];
} else if( test(/opera/) && test(/windows.nt.5/) && test(/htc|xda|mini|vario|samsung\-gt\-i8000|samsung\-sgh\-i9/)) {
device.type = defs.device.types[2];
} else if(( test(/windows.(nt|xp|me|9)/) && ! test(/phone/)) || test(/win(9|.9|nt)/) || test(/\(windows 8\)/)) {
device.type = defs.device.types[3];
} else if( test(/macintosh|powerpc/) && ! test(/silk/)) {
device.type = defs.device.types[3];
device.model = 'Mac';
} else if( test(/linux/) && test(/x11/)) {
device.type = defs.device.types[3];
} else if( test(/solaris|sunos|bsd/)) {
device.type = defs.device.types[3];
} else if( test(/cros/)) {
device.type = defs.device.types[3];
} else if( test(/bot|crawler|spider|yahoo|ia_archiver|covario-ids|findlinks|dataparksearch|larbin|mediapartners-google|ng-search|snappy|teoma|jeeves|tineye/) && ! test(/mobile/)) {
device.type = defs.device.types[3];
device.model = 'Crawler';
} else {
device.type = defs.device.types[3];
}
}
}
if( device.type !== 'Desktop' && device.type !== 'TV' ) {
device.orientation = 'landscape';
if( win.innerHeight > win.innerWidth ) {
device.orientation = 'portrait';
}
}
return device;
},
getScreen : function() {
var keys = Object.keys( defs.screens ).reverse();
for(var i = 0; i < keys.length; i++) {
var size = keys[i];
var width = defs.screens[size];
if( win.innerWidth > ( width - 1 ) ) {
return size;
}
}
},
getOS: function() {
var os = {
name : null,
addressRegisterSize : null,
};
if(_c.browser.device.model !== '') {
if(_c.browser.device.model === 'iPad' || _c.browser.device.model === 'iPhone' || _c.browser.device.model === 'iPod') {
os.name = 'iOS';
os = version(os, (test(/os\s([\d_]+)/) ? RegExp.$1 : '').replace(/_/g, '.'));
} else if(_c.browser.device.model === 'Android') {
os.name = 'Android';
os = version(os, (test(/Android\s([\d\.]+)/) ? RegExp.$1 : ''));
} else if(_c.browser.device.model === 'BlackBerry') {
os.name = 'BlackBerry';
os = version(os, (test(/version\/([^\s]+)/) ? RegExp.$1 : ''));
} else if(_c.browser.device.model === 'PlayBook') {
os.name = 'BlackBerry';
os = version(os, (test(/os ([^\s]+)/) ? RegExp.$1.replace(';', '') : ''));
}
}
if( ! os.name ) {
var options = [
'iOS',
'Android',
'BlackBerry',
'Opera Mini',
'Windows',
'Mac OS',
'OS X',
'AIX',
'Amiga',
'AROS',
'Bada',
'BeOS',
'Brew',
'Chrome OS',
'COS',
'Danger Hiptop',
'DragonFly BSD',
'Fire OS',
'Firefox OS',
'FreeBSD',
'GNU OS',
'Haiku OS',
'HP-UX',
'Inferno OS',
'IRIX',
'Joli OS',
'JVM (Java)',
'JVM',
'KIN OS',
'Linux',
'LiveArea',
'Maemo',
'MeeGo',
'MINIX 3',
'MorphOS',
'MSN TV (WebTV)',
'NetBSD',
'Nintendo 3DS',
'Nintendo DS',
'OpenBSD',
'OpenVM',
'Orbis OS',
'OS/2',
'OS/2 Warp',
'Palm OS',
'PClinuxOS',
'Plan 9',
'QNX x86pc',
'RISK OS',
'Sailfish',
'SCO OpenServer',
'SkyOS',
'Solaris',
'Syllable',
'Symbian OS',
'Tizen',
'Ubuntu Touch',
'webOS',
'Wii OS',
'Wii U OS',
'Xbox',
'XrossMediaBar (XMB)',
'Yun OS',
'unknown',
];
for( var i = 0; i < options.length; i++ ) {
var option = options[i];
if( uamatches( option ) ) {
os.name = option;
break;
}
}
}
if( ! os.name ) {
if(_c.browser.device.model !== '') {
if(_c.browser.device.model === 'ipad' || _c.browser.device.model === 'iphone' || _c.browser.device.model === 'ipod') {
os.name = 'ios';
version(os, (test(/os\s([\d_]+)/) ? RegExp.$1 : '').replace(/_/g, '.'));
} else if(_c.browser.device.model === 'Android') {
os.name = 'Android';
version(os, (test(/Android\s([\d\.]+)/) ? RegExp.$1 : ''));
} else if(_c.browser.device.model === 'BlackBerry') {
os.name = 'BlackBerry';
version(os, (test(/version\/([^\s]+)/) ? RegExp.$1 : ''));
} else if(_c.browser.device.model === 'PlayBook') {
os.name = 'BlackBerry';
version(os, (test(/os ([^\s]+)/) ? RegExp.$1.replace(';', '') : ''));
}
}
}
if( ! os.name ) {
if(uamatches('win') || uamatches('16bit')) {
os.name = 'windows';
if(uamatches('windows nt 6.3')) {
os = version(os, '8.1');
} else if(uamatches('windows nt 6.2') || test(/\(windows 8\)/)) {
os = version(os, '8');
} else if(uamatches('windows nt 6.1')) {
os = version(os, '7');
} else if(uamatches('windows nt 6.0')) {
os = version(os, 'vista');
} else if(uamatches('windows nt 5.2') || uamatches('windows nt 5.1') || uamatches('windows xp')) {
os = version(os, 'xp');
} else if(uamatches('windows nt 5.0') || uamatches('windows 2000')) {
os = version(os, '2k');
} else if(uamatches('winnt') || uamatches('windows nt')) {
os = version(os, 'nt');
} else if(uamatches('win98') || uamatches('windows 98')) {
os = version(os, '98');
} else {
if(uamatches('win95') || uamatches('windows 95')) {
os = version(os, '95');
}
}
} else if(uamatches('mac') || uamatches('darwin')) {
os.name = 'mac';
if(uamatches('68k') || uamatches('68000')) {
os = version(os, '68k');
} else if(uamatches('ppc') || uamatches('powerpc')) {
os = version(os, 'ppc');
} else {
if(uamatches('os x')) {
os = version(os, (test(/os\sx\s([\d_]+)/) ? RegExp.$1 : 'os x').replace(/_/g, '.'));
}
}
} else if(uamatches('webtv')) {
os.name = 'webtv';
} else if(uamatches('x11') || uamatches('inux')) {
os.name = 'linux';
} else if(uamatches('sunos')) {
os.name = 'sun';
} else if(uamatches('irix')) {
os.name = 'irix';
} else if(uamatches('freebsd')) {
os.name = 'freebsd';
} else {
if(uamatches('bsd')) {
os.name = 'bsd';
}
}
}
if(test(/\sx64|\sx86|\swin64|\swow64|\samd64/)) {
os.addressRegisterSize = '64bit';
} else {
os.addressRegisterSize = '32bit';
}
return os;
},
getBrowser: function() {
var browser = {
name : null,
engine : null,
};
if( ! test(/opera|webtv/) && ( test(/msie\s([\d\w\.]+)/) || uamatches('trident') ) ) {
browser.engine = 'trident';
browser.name = 'ie';
if( ! win.addEventListener && doc.documentMode && doc.documentMode === 7) {
browser = version(browser, '8.compat');
} else if(test(/trident.*rv[ :](\d+)\./)) {
browser = version(browser, RegExp.$1);
} else {
browser = version(browser, (test(/trident\/4\.0/) ? '8' : RegExp.$1));
}
} else if(uamatches('firefox')) {
browser.engine = 'gecko';
browser.name = 'firefox';
browser = version(browser, (test(/firefox\/([\d\w\.]+)/) ? RegExp.$1 : ''));
} else if(uamatches('gecko/')) {
browser.engine = 'gecko';
} else if(uamatches('opera') || uamatches('opr')) {
browser.name = 'opera';
browser.engine = 'presto';
browser = version(browser, (test(/version\/([\d\.]+)/) ? RegExp.$1 : (test(/opera(\s|\/)([\d\.]+)/) ? RegExp.$2 : '')));
} else if(uamatches('konqueror')) {
browser.name = 'konqueror';
} else if(uamatches('chrome')) {
browser.engine = 'webkit';
browser.name = 'chrome';
browser = version(browser, (test(/chrome\/([\d\.]+)/) ? RegExp.$1 : ''));
} else if(uamatches('iron')) {
browser.engine = 'webkit';
browser.name = 'iron';
} else if(uamatches('crios')) {
browser.name = 'chrome';
browser.engine = 'webkit';
browser = version(browser, (test(/crios\/([\d\.]+)/) ? RegExp.$1 : ''));
} else if(uamatches('applewebkit/')) {
browser.name = 'safari';
browser.engine = 'webkit';
browser = version(browser, (test(/version\/([\d\.]+)/) ? RegExp.$1 : ''));
} else if(uamatches('mozilla/')) {
browser.engine = 'gecko';
}
return browser;
},
getLanguage: function() {
return {
direction : _c.$html.attr('dir') || win.getComputedStyle(doc.body || doc.documentElement).direction || 'ltr',
code : win.navigator.userLanguage || win.navigator.language,
};
},
getPlugins: function() {
var output = [];
if( ! _c.utils.is.undefined( win.navigator.plugins ) ) {
for( var i = 0; i < win.navigator.plugins.length; i++ ) {
output.push( win.navigator.plugins[i] );
}
}
return output;
},
// add html tables
addHTMLClasses : function() {
var classes = [];
if( _c.browser.screen ) {
classes.push( 'screen-' + _c.browser.screen );
}
if( ! _c.utils.is.undefined( _c.browser.touch ) ) {
classes.push( _c.browser.touch ? 'touch' : 'notouch' );
}
if( classes.diff( this.classes ).length ) {
_c.$html.removeClass( this.classes.join(' ') );
_c.$html.addClass( classes.join(' ') );
this.classes = classes;
}
}
});
});