/**
 * @class Ext
 */
Ext.apply(Ext, {
    
/** * The version of the framework * @type String */ version : '1.0.0', versionDetail : { major : 1, minor : 0, patch : 0 },
/** * Sets up a page for use on a mobile device. * @param {Object} config * * Valid configurations are: * */ setup: function(config) { if (config && typeof config == 'object') { if (config.addMetaTags !== false) { this.addMetaTags(config); } if (Ext.isFunction(config.onReady)) { var me = this; Ext.onReady(function() { var args = arguments; if (config.fullscreen !== false) { Ext.Viewport.init(function() { config.onReady.apply(me, args); }); } else { config.onReady.apply(this, args); } }, config.scope); } } },
/** * Return the dom node for the passed String (id), dom node, or Ext.Element. * Here are some examples: *

// gets dom node based on id
var elDom = Ext.getDom('elId');
// gets dom node based on the dom node
var elDom1 = Ext.getDom(elDom);

// If we don't know if we are working with an
// Ext.Element or a dom node use Ext.getDom
function(el){
 var dom = Ext.getDom(el);
 // do something with the dom node
}
       
* Note: the dom node to be found actually needs to exist (be rendered, etc) * when this method is called to be successful. * @param {Mixed} el * @return HTMLElement */ getDom : function(el) { if (!el || !document) { return null; } return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el); },
/** *

Removes this element from the document, removes all DOM event listeners, and deletes the cache reference. * All DOM event listeners are removed from this element. If {@link Ext#enableNestedListenerRemoval} is * true, then DOM event listeners are also removed from all child nodes. The body node * will be ignored if passed in.

* @param {HTMLElement} node The node to remove */ removeNode : function(node) { if (node && node.parentNode && node.tagName != 'BODY') { Ext.EventManager.removeAll(node); node.parentNode.removeChild(node); delete Ext.cache[node.id]; } }, /** * @private * Creates meta tags for a given config object. This is usually just called internally from Ext.setup - see * that method for full usage. Extracted into its own function so that Ext.Application and other classes can * call it without invoking all of the logic inside Ext.setup. * @param {Object} config The meta tag configuration object */ addMetaTags: function(config) { if (!Ext.isObject(config)) { return; } var head = Ext.get(document.getElementsByTagName('head')[0]), tag, precomposed; /* * The viewport meta tag. This disables user scaling. This is supported * on most Android phones and all iOS devices and will probably be supported * on most future devices (like Blackberry, Palm etc). */ if (!Ext.is.Desktop) { tag = Ext.get(document.createElement('meta')); tag.set({ name: 'viewport', content: 'width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0;' }); head.appendChild(tag); } /* * We want to check now for iOS specific meta tags. Unfortunately most * of these are not supported on devices other then iOS. */ if (Ext.is.iOS) { /* * On iOS, if you save to home screen, you can decide if you want * to launch the app fullscreen (without address bar). You can also * change the styling of the status bar at the top of the screen. */ if (config.fullscreen !== false) { tag = Ext.get(document.createElement('meta')); tag.set({ name: 'apple-mobile-web-app-capable', content: 'yes' }); head.appendChild(tag); if (Ext.isString(config.statusBarStyle)) { tag = Ext.get(document.createElement('meta')); tag.set({ name: 'apple-mobile-web-app-status-bar-style', content: config.statusBarStyle }); head.appendChild(tag); } } /* * iOS allows you to specify a startup screen. This is displayed during * the startup of your app if you save to your homescreen. Since we could * be dealing with an iPad or iPhone/iPod, we have a tablet startup screen * and a phone startup screen. */ if (config.tabletStartupScreen && Ext.is.iPad) { tag = Ext.get(document.createElement('link')); tag.set({ rel: 'apple-touch-startup-image', href: config.tabletStartupScreen }); head.appendChild(tag); } if (config.phoneStartupScreen && !Ext.is.iPad) { tag = Ext.get(document.createElement('link')); tag.set({ rel: 'apple-touch-startup-image', href: config.phoneStartupScreen }); head.appendChild(tag); } /* * On iOS you can specify the icon used when you save the app to your * homescreen. You can set an icon that will be used for both iPads * and iPhone/iPod, or you can specify specific icons for both. */ if (config.icon) { config.phoneIcon = config.tabletIcon = config.icon; } precomposed = (config.glossOnIcon === false) ? '-precomposed' : ''; if (Ext.is.iPad && Ext.isString(config.tabletIcon)) { tag = Ext.get(document.createElement('link')); tag.set({ rel: 'apple-touch-icon' + precomposed, href: config.tabletIcon }); head.appendChild(tag); } else if (!Ext.is.iPad && Ext.isString(config.phoneIcon)) { tag = Ext.get(document.createElement('link')); tag.set({ rel: 'apple-touch-icon' + precomposed, href: config.phoneIcon }); head.appendChild(tag); } } } }); Ext.Viewport = new (Ext.extend(Ext.util.Observable, { constructor: function() { this.addEvents( 'orientationchange', 'resize' ); if (Ext.supports.OrientationChange) { window.addEventListener('orientationchange', Ext.createDelegate(this.onOrientationChange, this), false); } else { window.addEventListener('resize', Ext.createDelegate(this.onResize, this), false); } if (!Ext.desktop) { document.addEventListener('touchstart', Ext.createDelegate(this.onTouchStartCapturing, this), true); document.addEventListener('touchmove', Ext.createDelegate(this.onTouchMoveBubbling, this), false); } this.stretchSizes = {}; }, init: function(fn) { var me = this, stretchSize = Math.max(window.innerHeight, window.innerWidth) * 2; me.updateOrientation(); if (!Ext.is.Desktop) { me.stretchEl = Ext.getBody().createChild({ cls: 'x-body-stretcher', style: 'height: ' + stretchSize + 'px; width:' + (Ext.is.Android ? stretchSize + 'px' : '1px') }); } setTimeout(function() { me.scrollToTop(); setTimeout(function() { Ext.getBody().setStyle('overflow', 'hidden'); if (Ext.is.Android && me.stretchEl) { me.stretchEl.remove(); delete me.stretchEl; } if (fn) { setTimeout(function() { fn(); if (!Ext.is.Android) { me.updateBodySize(); } }, 500); } }, 200); }, 500); if (!Ext.is.Android) { this.on('orientationchange', function() { if (Ext.currentlyFocusedField) { Ext.currentlyFocusedField.blur(); } }); } }, showStretchEl: function() { if (!Ext.is.Android && this.stretchEl) { this.stretchEl.setStyle('display', 'block'); } }, hideStretchEl: function() { if (!Ext.is.Android && this.stretchEl) { this.stretchEl.setStyle('display', 'none'); } }, updateBodySize: function() { // Why Ext.getBody() is undefined in here? WTF! document.body.style.width = window.innerWidth + 'px'; document.body.style.height = window.innerHeight + 'px'; }, updateOrientation: function() { this.lastSize = this.getSize(); this.orientation = this.getOrientation(); }, onTouchStartCapturing: function(e) { var target = e.target; if (!Ext.currentlyFocusedField && !Ext.is.Android) { this.scrollToTop(); } if (Ext.is.Android) { if (target.nodeType == 3) { target = target.parentNode; } if (target.tagName && (/input|select|textarea/i.test(target.tagName))) { return; } e.preventDefault(); e.stopPropagation(); } }, onTouchMoveBubbling: function(e) { e.preventDefault(); e.stopPropagation(); }, onOrientationChange: function() { var me = this; this.updateOrientation(); this.fireEvent('orientationchange', this, this.orientation); if (!Ext.is.Android) { this.scrollToTop(1, function() { me.updateBodySize(); me.fireResizeEvent(); }, true); } else { this.scrollToTop(100, function() { me.fireResizeEvent(); }); } }, fireResizeEvent: function() { var me = this; var size = me.getSize(); if (Ext.is.Android) { if (this.resizeEventTimer) { clearTimeout(this.resizeEventTimer); } this.resizeEventTimer = setTimeout(function() { me.fireEvent('resize', me, me.getSize()); }, 500); } else { me.fireEvent('resize', me, me.getSize()); } }, onResize: function() { if (this.orientation != this.getOrientation()) { this.onOrientationChange(); } else { var size = this.getSize(); if (Ext.is.Android) { if ((size.width == this.lastSize.width && size.height > this.lastSize.height) || (size.height == this.lastSize.height && size.width > this.lastSize.width)) { this.fireEvent('resize', this, size); } } else { this.fireEvent('resize', this, size); } } }, getSize: function() { return { width: window.innerWidth, height: window.innerHeight }; }, getOffset: function() { return { x: window.pageXOffset, y: window.pageYOffset }; }, scrollToTop: function(delay, fn) { if (delay) { setTimeout(function() { window.scrollTo(0, Ext.is.Android ? -1 : 0); if (fn) { setTimeout(fn, 0); } }, delay); } else { window.scrollTo(0, Ext.is.Android ? -1 : 0); if (fn) { setTimeout(fn, 0); } } }, getOrientation: function() { var size = this.getSize(); if (window.hasOwnProperty('orientation')) { return (window.orientation == 0 || window.orientation == 180) ? 'portrait' : 'landscape'; } else { if (Ext.is.Android) { if ((size.width == this.lastSize.width && size.height < this.lastSize.height) || (size.height == this.lastSize.height && size.width < this.lastSize.width)) { return this.orientation; } } return (window.innerHeight > window.innerWidth) ? 'portrait' : 'landscape'; } } })); //Initialize doc classes and feature detections (function() { var initExt = function() { // find the body element var bd = Ext.getBody(), cls = []; if (!bd) { return false; } var Is = Ext.is; if (Is.Phone) { cls.push('x-phone'); } else if (Is.Tablet) { cls.push('x-tablet'); } else if (Is.Desktop) { cls.push('x-desktop'); } if (Is.iPad) { cls.push('x-ipad'); } if (Is.iOS) { cls.push('x-ios'); } if (Is.Android) { cls.push('x-android'); } if (Is.Standalone) { cls.push('x-standalone'); } if (cls.length) { bd.addCls(cls); } return true; }; if (!initExt()) { Ext.onReady(initExt); } })();