/**
* @class Ext.is
*
* Determines information about the current platform the application is running on.
*
* @singleton
*/
Ext.is = {
init : function(navigator) {
var platforms = this.platforms,
ln = platforms.length,
i, platform;
navigator = navigator || window.navigator;
for (i = 0; i < ln; i++) {
platform = platforms[i];
this[platform.identity] = platform.regex.test(navigator[platform.property]);
}
/**
* @property Desktop True if the browser is running on a desktop machine
* @type {Boolean}
*/
this.Desktop = this.Mac || this.Windows || (this.Linux && !this.Android);
/**
* @property Tablet True if the browser is running on a tablet (iPad)
*/
this.Tablet = this.iPad;
/**
* @property Phone True if the browser is running on a phone.
* @type {Boolean}
*/
this.Phone = !this.Desktop && !this.Tablet;
/**
* @property iOS True if the browser is running on iOS
* @type {Boolean}
*/
this.iOS = this.iPhone || this.iPad || this.iPod;
/**
* @property Standalone Detects when application has been saved to homescreen.
* @type {Boolean}
*/
this.Standalone = !!window.navigator.standalone;
},
/**
* @property iPhone True when the browser is running on a iPhone
* @type {Boolean}
*/
platforms: [{
property: 'platform',
regex: /iPhone/i,
identity: 'iPhone'
},
/**
* @property iPod True when the browser is running on a iPod
* @type {Boolean}
*/
{
property: 'platform',
regex: /iPod/i,
identity: 'iPod'
},
/**
* @property iPad True when the browser is running on a iPad
* @type {Boolean}
*/
{
property: 'userAgent',
regex: /iPad/i,
identity: 'iPad'
},
/**
* @property Blackberry True when the browser is running on a Blackberry
* @type {Boolean}
*/
{
property: 'userAgent',
regex: /Blackberry/i,
identity: 'Blackberry'
},
/**
* @property Android True when the browser is running on an Android device
* @type {Boolean}
*/
{
property: 'userAgent',
regex: /Android/i,
identity: 'Android'
},
/**
* @property Mac True when the browser is running on a Mac
* @type {Boolean}
*/
{
property: 'platform',
regex: /Mac/i,
identity: 'Mac'
},
/**
* @property Windows True when the browser is running on Windows
* @type {Boolean}
*/
{
property: 'platform',
regex: /Win/i,
identity: 'Windows'
},
/**
* @property Linux True when the browser is running on Linux
* @type {Boolean}
*/
{
property: 'platform',
regex: /Linux/i,
identity: 'Linux'
}]
};
Ext.is.init();
/**
* @class Ext.supports
*
* Determines information about features are supported in the current environment
*
* @singleton
*/
Ext.supports = {
init : function() {
var doc = document,
div = doc.createElement('div'),
tests = this.tests,
ln = tests.length,
i, test;
div.innerHTML = [
'',
''
].join('');
doc.body.appendChild(div);
for (i = 0; i < ln; i++) {
test = tests[i];
this[test.identity] = test.fn.call(this, doc, div);
}
doc.body.removeChild(div);
},
/**
* @property ClassList True if document environment supports the HTML5 classList API.
* @type {Boolean}
*/
ClassList: !!document.documentElement.classList,
/**
* @property OrientationChange True if the device supports orientation change
* @type {Boolean}
*/
OrientationChange: ((typeof window.orientation != 'undefined') && ('onorientationchange' in window)),
/**
* @property DeviceMotion True if the device supports device motion (acceleration and rotation rate)
* @type {Boolean}
*/
DeviceMotion: ('ondevicemotion' in window),
/**
* @property Touch True if the device supports touch
* @type {Boolean}
*/
// is.Desktop is needed due to the bug in Chrome 5.0.375, Safari 3.1.2
// and Safari 4.0 (they all have 'ontouchstart' in the window object).
Touch: ('ontouchstart' in window) && (!Ext.is.Desktop),
tests: [
/**
* @property Transitions True if the device supports CSS3 Transitions
* @type {Boolean}
*/
{
identity: 'Transitions',
fn: function(doc, div) {
var prefix = [
'webkit',
'Moz',
'o',
'ms',
'khtml'
],
TE = 'TransitionEnd',
transitionEndName = [
prefix[0] + TE,
'transitionend', //Moz bucks the prefixing convention
prefix[2] + TE,
prefix[3] + TE,
prefix[4] + TE
],
ln = prefix.length,
i = 0,
out = false;
div = Ext.get(div);
for (; i < ln; i++) {
if (div.getStyle(prefix[i] + "TransitionProperty")) {
Ext.supports.CSS3Prefix = prefix[i];
Ext.supports.CSS3TransitionEnd = transitionEndName[i];
out = true;
break;
}
}
return out;
}
},
/**
* @property RightMargin True if the device supports right margin.
* See https://bugs.webkit.org/show_bug.cgi?id=13343 for why this is needed.
* @type {Boolean}
*/
{
identity: 'RightMargin',
fn: function(doc, div, view) {
view = doc.defaultView;
return !(view && view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px');
}
},
/**
* @property TransparentColor True if the device supports transparent color
* @type {Boolean}
*/
{
identity: 'TransparentColor',
fn: function(doc, div, view) {
view = doc.defaultView;
return !(view && view.getComputedStyle(div.lastChild, null).backgroundColor != 'transparent');
}
},
/**
* @property ComputedStyle True if the browser supports document.defaultView.getComputedStyle()
* @type {Boolean}
*/
{
identity: 'ComputedStyle',
fn: function(doc, div, view) {
view = doc.defaultView;
return view && view.getComputedStyle;
}
},
/**
* @property SVG True if the device supports SVG
* @type {Boolean}
*/
{
identity: 'SVG',
fn: function(doc) {
return !!doc.createElementNS && !!doc.createElementNS( "http:/" + "/www.w3.org/2000/svg", "svg").createSVGRect;
}
},
/**
* @property Canvas True if the device supports Canvas
* @type {Boolean}
*/
{
identity: 'Canvas',
fn: function(doc) {
return !!doc.createElement('canvas').getContext;
}
},
/**
* @property VML True if the device supports VML
* @type {Boolean}
*/
{
identity: 'VML',
fn: function(doc) {
var d = doc.createElement("div");
d.innerHTML = "";
return (d.childNodes.length == 2);
}
},
/**
* @property Float True if the device supports CSS float
* @type {Boolean}
*/
{
identity: 'Float',
fn: function(doc, div) {
return !!div.lastChild.style.cssFloat;
}
},
/**
* @property AudioTag True if the device supports the HTML5 audio tag
* @type {Boolean}
*/
{
identity: 'AudioTag',
fn: function(doc) {
return !!doc.createElement('audio').canPlayType;
}
},
/**
* @property History True if the device supports HTML5 history
* @type {Boolean}
*/
{
identity: 'History',
fn: function() {
return !!(window.history && history.pushState);
}
},
/**
* @property CSS3DTransform True if the device supports CSS3DTransform
* @type {Boolean}
*/
{
identity: 'CSS3DTransform',
fn: function() {
return (typeof WebKitCSSMatrix != 'undefined' && new WebKitCSSMatrix().hasOwnProperty('m41'));
}
},
/**
* @property CSS3LinearGradient True if the device supports CSS3 linear gradients
* @type {Boolean}
*/
{
identity: 'CSS3LinearGradient',
fn: function(doc, div) {
var property = 'background-image:',
webkit = '-webkit-gradient(linear, left top, right bottom, from(black), to(white))',
w3c = 'linear-gradient(left top, black, white)',
moz = '-moz-' + w3c,
options = [property + webkit, property + w3c, property + moz];
div.style.cssText = options.join(';');
return ("" + div.style.backgroundImage).indexOf('gradient') !== -1;
}
},
/**
* @property CSS3BorderRadius True if the device supports CSS3 border radius
* @type {Boolean}
*/
{
identity: 'CSS3BorderRadius',
fn: function(doc, div) {
var domPrefixes = ['borderRadius', 'BorderRadius', 'MozBorderRadius', 'WebkitBorderRadius', 'OBorderRadius', 'KhtmlBorderRadius'],
pass = false,
i;
for (i = 0; i < domPrefixes.length; i++) {
if (document.body.style[domPrefixes[i]] !== undefined) {
return true;
}
}
return pass;
}
},
/**
* @property GeoLocation True if the device supports GeoLocation
* @type {Boolean}
*/
{
identity: 'GeoLocation',
fn: function() {
return (typeof navigator != 'undefined' && typeof navigator.geolocation != 'undefined') || (typeof google != 'undefined' && typeof google.gears != 'undefined');
}
},
/**
* @property MouseEnterLeave True if the browser supports mouseenter and mouseleave events
* @type {Boolean}
*/
{
identity: 'MouseEnterLeave',
fn: function(doc, div){
return ('onmouseenter' in div && 'onmouseleave' in div);
}
},
/**
* @property MouseWheel True if the browser supports the mousewheel event
* @type {Boolean}
*/
{
identity: 'MouseWheel',
fn: function(doc, div) {
return ('onmousewheel' in div);
}
},
/**
* @property Opacity True if the browser supports normal css opacity
* @type {Boolean}
*/
{
identity: 'Opacity',
fn: function(doc, div){
// Not a strict equal comparison in case opacity can be converted to a number.
if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
return false;
}
div.firstChild.style.cssText = 'opacity:0.73';
return div.firstChild.style.opacity == '0.73';
}
},
/**
* @property Placeholder True if the browser supports the HTML5 placeholder attribute on inputs
* @type {Boolean}
*/
{
identity: 'Placeholder',
fn: function(doc) {
return 'placeholder' in doc.createElement('input');
}
},
/**
* @property BoundingClientRect True if the browser supports the getBoundingClientRect method on elements
* @type {Boolean}
*/
{
identity: 'BoundingClientRect',
fn: function(doc, div) {
return Ext.isFunction(div.getBoundingClientRect);
}
}
]
};