/**
* @class Ext.env.FeatureDetector
*/
Ext.define('Ext.env.FeatureDetector', {
statics: {
defaultTests: {
Canvas: function() {
var element = this.getTestElement('canvas');
return !!(element && element.getContext && element.getContext('2d'));
},
SVG: function() {
var doc = Ext.global.document;
return !!(doc.createElementNS && !!doc.createElementNS("http:/" + "/www.w3.org/2000/svg", "svg").createSVGRect);
},
VML: function() {
var element = this.getTestElement(),
ret = false;
element.innerHTML = "<!--[if vml]><br><br><![endif]-->";
ret = (element.childNodes.length === 2);
element.innerHTML = "";
return ret;
},
Touch: function() {
return ('ontouchstart' in Ext.global) && !(Ext.platform && Ext.platform.name.match(/Windows|MacOSX|Linux/));
},
Orientation: function() {
return ('orientation' in Ext.global);
},
Geolocation: function() {
return !!Ext.global.navigator.geolocation;
},
SqlDatabase: function() {
return !!Ext.global.openDatabase;
},
Websockets: function() {
return 'WebSocket' in Ext.global;
},
History: function() {
return !!(Ext.global.history && Ext.global.history.pushState);
},
CSSTransforms: function() {
return this.isStyleSupported('transform');
},
CSS3DTransforms: function() {
return this.has('csstransforms') && this.isStyleSupported('perspective');
},
CSSAnimations: function() {
return this.isStyleSupported('animationName');
},
CSSTransitions: function() {
return this.isStyleSupported('transitionProperty');
},
Audio: function() {
return !!this.getTestElement('audio').canPlayType;
},
Video: function() {
return !!this.getTestElement('video').canPlayType;
}
},
stylePrefixes: ['Webkit', 'Moz', 'O', 'ms']
},
constructor: function() {
this.tests = {};
this.testElements = {};
this.registerTests(this.self.defaultTests, true);
return this;
},
has: function(name) {
if (!this.hasTest(name)) {
return false;
}
else if (this.has.hasOwnProperty(name)) {
return this.has[name];
}
else {
return this.getTestResult(name);
}
},
getTestResult: function(name) {
return !!this.getTest(name).call(this);
},
getTestElement: function(tag) {
if (!tag) {
tag = 'div';
}
if (!this.testElements[tag]) {
this.testElements[tag] = Ext.global.document.createElement(tag);
}
return this.testElements[tag];
},
registerTest: function(name, fn, isDefault) {
//<debug>
if (this.hasTest(name)) {
Ext.Error.raise({
sourceClass: "Ext.env.FeatureDetector",
sourceMethod: "registerTest",
msg: "Test name " + name + " has already been registered"
});
}
//<debug>
this.tests[name] = fn;
if (isDefault) {
this.has[name] = this.getTestResult(name);
}
return this;
},
registerTests: function(tests, isDefault) {
Ext.Object.each(tests, function(name, fn) {
this.registerTest(name, fn, isDefault);
}, this);
return this;
},
hasTest: function(name) {
return this.tests.hasOwnProperty(name);
},
getTest: function(name) {
//<debug>
if (!this.hasTest(name)) {
Ext.Error.raise({
sourceClass: "Ext.env.FeatureDetector",
sourceMethod: "getTest",
msg: "Test name " + name + " does not exist"
});
}
//<debug>
return this.tests[name];
},
getTests: function() {
return this.tests;
},
isStyleSupported: function(name, tag) {
var elementStyle = this.getTestElement(tag).style,
cName = Ext.String.capitalize(name),
i = this.self.stylePrefixes.length;
if (elementStyle[name] !== undefined) {
return true;
}
while (i--) {
if (elementStyle[this.self.stylePrefixes[i] + cName] !== undefined) {
return true;
}
}
return false;
},
isEventSupported: function(name, tag) {
var element = this.getTestElement(tag),
eventName = 'on' + name,
isSupported = false;
// When using `setAttribute`, IE skips "unload", WebKit skips
// "unload" and "resize", whereas `in` "catches" those
isSupported = (eventName in element);
if (!isSupported) {
if (element.setAttribute && element.removeAttribute) {
element.setAttribute(eventName, '');
isSupported = typeof element[eventName] === 'function';
// If property was created, "remove it" (by setting value to `undefined`)
if (typeof element[eventName] !== 'undefined') {
element[eventName] = undefined;
}
element.removeAttribute(eventName);
}
}
return isSupported;
}
}, function() {
/*
* Global convenient instance of {@link Ext.env.FeatureDetector Ext.env.FeatureDetector}
* @member Ext features
*/
Ext.features = new Ext.env.FeatureDetector();
});