4 * Determines information about the current platform the application is running on.
9 init : function(navigator) {
10 var platforms = this.platforms,
11 ln = platforms.length,
14 navigator = navigator || window.navigator;
16 for (i = 0; i < ln; i++) {
17 platform = platforms[i];
18 this[platform.identity] = platform.regex.test(navigator[platform.property]);
22 * @property Desktop True if the browser is running on a desktop machine
25 this.Desktop = this.Mac || this.Windows || (this.Linux && !this.Android);
27 * @property Tablet True if the browser is running on a tablet (iPad)
29 this.Tablet = this.iPad;
31 * @property Phone True if the browser is running on a phone.
34 this.Phone = !this.Desktop && !this.Tablet;
36 * @property iOS True if the browser is running on iOS
39 this.iOS = this.iPhone || this.iPad || this.iPod;
42 * @property Standalone Detects when application has been saved to homescreen.
45 this.Standalone = !!window.navigator.standalone;
49 * @property iPhone True when the browser is running on a iPhone
59 * @property iPod True when the browser is running on a iPod
69 * @property iPad True when the browser is running on a iPad
73 property: 'userAgent',
79 * @property Blackberry True when the browser is running on a Blackberry
83 property: 'userAgent',
85 identity: 'Blackberry'
89 * @property Android True when the browser is running on an Android device
93 property: 'userAgent',
99 * @property Mac True when the browser is running on a Mac
103 property: 'platform',
109 * @property Windows True when the browser is running on Windows
113 property: 'platform',
119 * @property Linux True when the browser is running on Linux
123 property: 'platform',
132 * @class Ext.supports
134 * Determines information about features are supported in the current environment
141 div = doc.createElement('div'),
147 '<div style="height:30px;width:50px;">',
148 '<div style="height:20px;width:20px;"></div>',
150 '<div style="width: 200px; height: 200px; position: relative; padding: 5px;">',
151 '<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></div>',
153 '<div style="float:left; background-color:transparent;"></div>'
156 doc.body.appendChild(div);
158 for (i = 0; i < ln; i++) {
160 this[test.identity] = test.fn.call(this, doc, div);
163 doc.body.removeChild(div);
167 * @property CSS3BoxShadow True if document environment supports the CSS3 box-shadow style.
170 CSS3BoxShadow: Ext.isDefined(document.documentElement.style.boxShadow),
173 * @property ClassList True if document environment supports the HTML5 classList API.
176 ClassList: !!document.documentElement.classList,
179 * @property OrientationChange True if the device supports orientation change
182 OrientationChange: ((typeof window.orientation != 'undefined') && ('onorientationchange' in window)),
185 * @property DeviceMotion True if the device supports device motion (acceleration and rotation rate)
188 DeviceMotion: ('ondevicemotion' in window),
191 * @property Touch True if the device supports touch
194 // is.Desktop is needed due to the bug in Chrome 5.0.375, Safari 3.1.2
195 // and Safari 4.0 (they all have 'ontouchstart' in the window object).
196 Touch: ('ontouchstart' in window) && (!Ext.is.Desktop),
200 * @property Transitions True if the device supports CSS3 Transitions
204 identity: 'Transitions',
205 fn: function(doc, div) {
213 TE = 'TransitionEnd',
214 transitionEndName = [
216 'transitionend', //Moz bucks the prefixing convention
225 for (; i < ln; i++) {
226 if (div.getStyle(prefix[i] + "TransitionProperty")) {
227 Ext.supports.CSS3Prefix = prefix[i];
228 Ext.supports.CSS3TransitionEnd = transitionEndName[i];
238 * @property RightMargin True if the device supports right margin.
239 * See https://bugs.webkit.org/show_bug.cgi?id=13343 for why this is needed.
243 identity: 'RightMargin',
244 fn: function(doc, div) {
245 var view = doc.defaultView;
246 return !(view && view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px');
251 * @property DisplayChangeInputSelectionBug True if INPUT elements lose their
252 * selection when their display style is changed. Essentially, if a text input
253 * has focus and its display style is changed, the I-beam disappears.
255 * This bug is encountered due to the work around in place for the {@link RightMargin}
256 * bug. This has been observed in Safari 4.0.4 and older, and appears to be fixed
257 * in Safari 5. It's not clear if Safari 4.1 has the bug, but it has the same WebKit
258 * version number as Safari 5 (according to http://unixpapa.com/js/gecko.html).
261 identity: 'DisplayChangeInputSelectionBug',
263 var webKitVersion = Ext.webKitVersion;
264 // WebKit but older than Safari 5 or Chrome 6:
265 return 0 < webKitVersion && webKitVersion < 533;
270 * @property DisplayChangeTextAreaSelectionBug True if TEXTAREA elements lose their
271 * selection when their display style is changed. Essentially, if a text area has
272 * focus and its display style is changed, the I-beam disappears.
274 * This bug is encountered due to the work around in place for the {@link RightMargin}
275 * bug. This has been observed in Chrome 10 and Safari 5 and older, and appears to
276 * be fixed in Chrome 11.
279 identity: 'DisplayChangeTextAreaSelectionBug',
281 var webKitVersion = Ext.webKitVersion;
286 (Chrome) Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US)
287 AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.127
289 (Safari) Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-us)
290 AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5
295 (Chrome) Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_7)
296 AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.57
299 return 0 < webKitVersion && webKitVersion < 534.24;
304 * @property TransparentColor True if the device supports transparent color
308 identity: 'TransparentColor',
309 fn: function(doc, div, view) {
310 view = doc.defaultView;
311 return !(view && view.getComputedStyle(div.lastChild, null).backgroundColor != 'transparent');
316 * @property ComputedStyle True if the browser supports document.defaultView.getComputedStyle()
320 identity: 'ComputedStyle',
321 fn: function(doc, div, view) {
322 view = doc.defaultView;
323 return view && view.getComputedStyle;
328 * @property SVG True if the device supports SVG
334 return !!doc.createElementNS && !!doc.createElementNS( "http:/" + "/www.w3.org/2000/svg", "svg").createSVGRect;
339 * @property Canvas True if the device supports Canvas
345 return !!doc.createElement('canvas').getContext;
350 * @property VML True if the device supports VML
356 var d = doc.createElement("div");
357 d.innerHTML = "<!--[if vml]><br><br><![endif]-->";
358 return (d.childNodes.length == 2);
363 * @property Float True if the device supports CSS float
368 fn: function(doc, div) {
369 return !!div.lastChild.style.cssFloat;
374 * @property AudioTag True if the device supports the HTML5 audio tag
378 identity: 'AudioTag',
380 return !!doc.createElement('audio').canPlayType;
385 * @property History True if the device supports HTML5 history
391 return !!(window.history && history.pushState);
396 * @property CSS3DTransform True if the device supports CSS3DTransform
400 identity: 'CSS3DTransform',
402 return (typeof WebKitCSSMatrix != 'undefined' && new WebKitCSSMatrix().hasOwnProperty('m41'));
407 * @property CSS3LinearGradient True if the device supports CSS3 linear gradients
411 identity: 'CSS3LinearGradient',
412 fn: function(doc, div) {
413 var property = 'background-image:',
414 webkit = '-webkit-gradient(linear, left top, right bottom, from(black), to(white))',
415 w3c = 'linear-gradient(left top, black, white)',
417 options = [property + webkit, property + w3c, property + moz];
419 div.style.cssText = options.join(';');
421 return ("" + div.style.backgroundImage).indexOf('gradient') !== -1;
426 * @property CSS3BorderRadius True if the device supports CSS3 border radius
430 identity: 'CSS3BorderRadius',
431 fn: function(doc, div) {
432 var domPrefixes = ['borderRadius', 'BorderRadius', 'MozBorderRadius', 'WebkitBorderRadius', 'OBorderRadius', 'KhtmlBorderRadius'],
435 for (i = 0; i < domPrefixes.length; i++) {
436 if (document.body.style[domPrefixes[i]] !== undefined) {
445 * @property GeoLocation True if the device supports GeoLocation
449 identity: 'GeoLocation',
451 return (typeof navigator != 'undefined' && typeof navigator.geolocation != 'undefined') || (typeof google != 'undefined' && typeof google.gears != 'undefined');
455 * @property MouseEnterLeave True if the browser supports mouseenter and mouseleave events
459 identity: 'MouseEnterLeave',
460 fn: function(doc, div){
461 return ('onmouseenter' in div && 'onmouseleave' in div);
465 * @property MouseWheel True if the browser supports the mousewheel event
469 identity: 'MouseWheel',
470 fn: function(doc, div) {
471 return ('onmousewheel' in div);
475 * @property Opacity True if the browser supports normal css opacity
480 fn: function(doc, div){
481 // Not a strict equal comparison in case opacity can be converted to a number.
482 if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
485 div.firstChild.style.cssText = 'opacity:0.73';
486 return div.firstChild.style.opacity == '0.73';
490 * @property Placeholder True if the browser supports the HTML5 placeholder attribute on inputs
494 identity: 'Placeholder',
496 return 'placeholder' in doc.createElement('input');
501 * @property Direct2DBug True if when asking for an element's dimension via offsetWidth or offsetHeight,
502 * getBoundingClientRect, etc. the browser returns the subpixel width rounded to the nearest pixel.
506 identity: 'Direct2DBug',
508 return Ext.isString(document.body.style.msTransformOrigin);
512 * @property BoundingClientRect True if the browser supports the getBoundingClientRect method on elements
516 identity: 'BoundingClientRect',
517 fn: function(doc, div) {
518 return Ext.isFunction(div.getBoundingClientRect);
522 identity: 'IncludePaddingInWidthCalculation',
523 fn: function(doc, div){
524 var el = Ext.get(div.childNodes[1].firstChild);
525 return el.getWidth() == 210;
529 identity: 'IncludePaddingInHeightCalculation',
530 fn: function(doc, div){
531 var el = Ext.get(div.childNodes[1].firstChild);
532 return el.getHeight() == 210;
537 * @property ArraySort True if the Array sort native method isn't bugged.
541 identity: 'ArraySort',
543 var a = [1,2,3,4,5].sort(function(){ return 0; });
544 return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
548 * @property Range True if browser support document.createRange native method.
554 return !!document.createRange;
558 * @property CreateContextualFragment True if browser support CreateContextualFragment range native methods.
562 identity: 'CreateContextualFragment',
564 var range = Ext.supports.Range ? document.createRange() : false;
566 return range && !!range.createContextualFragment;
571 * @property WindowOnError True if browser supports window.onerror.
575 identity: 'WindowOnError',
577 // sadly, we cannot feature detect this...
578 return Ext.isIE || Ext.isGecko || Ext.webKitVersion >= 534.16; // Chrome 10+