UNPKG

@qooxdoo/framework

Version:

The JS Framework for Coders

387 lines (330 loc) 10.4 kB
/* ************************************************************************ qooxdoo - the new era of web development http://qooxdoo.org Copyright: 2007-2008 1&1 Internet AG, Germany, http://www.1und1.de License: MIT: https://opensource.org/licenses/MIT See the LICENSE file in the project's top-level directory for details. Authors: * Sebastian Werner (wpbasti) * Fabian Jakobs (fjakobs) ************************************************************************ */ /** * This handler provides events for qooxdoo application startup/shutdown logic. * * NOTE: Instances of this class must be disposed of after use * * @require(qx.bom.client.Engine) */ qx.Class.define("qx.event.handler.Application", { extend: qx.core.Object, implement: [qx.event.IEventHandler, qx.core.IDisposable], /* ***************************************************************************** CONSTRUCTOR ***************************************************************************** */ /** * Create a new instance * * @param manager {qx.event.Manager} Event manager for the window to use */ construct(manager) { super(); // Define shorthands this._window = manager.getWindow(); this.__domReady = false; this.__loaded = false; this.__isReady = false; this.__isInitialized = false; this.__isUnloaded = false; // Initialize observers this._initObserver(); // Store instance (only supported for main app window, this // is the reason why this is OK here) qx.event.handler.Application.$$instance = this; }, /* ***************************************************************************** STATICS ***************************************************************************** */ statics: { /** @type {Integer} Priority of this handler */ PRIORITY: qx.event.Registration.PRIORITY_NORMAL, /** @type {Map} Supported event types */ SUPPORTED_TYPES: { ready: 1, shutdown: 1 }, /** @type {Integer} Which target check to use */ TARGET_CHECK: qx.event.IEventHandler.TARGET_WINDOW, /** @type {Integer} Whether the method "canHandleEvent" must be called */ IGNORE_CAN_HANDLE: true, /** * Sends the currently running application the ready signal. Used * exclusively by package loader system. * * @internal */ onScriptLoaded() { var inst = qx.event.handler.Application.$$instance; if (inst) { inst.__fireReady(); } }, /** * Notifies that the application has finished initialization * * @internal */ onAppInstanceInitialized() { var inst = qx.event.handler.Application.$$instance; if (inst) { inst.__fireAppInstanceInitialized(); } } }, /* ***************************************************************************** MEMBERS ***************************************************************************** */ members: { /* --------------------------------------------------------------------------- EVENT HANDLER INTERFACE --------------------------------------------------------------------------- */ // interface implementation canHandleEvent(target, type) {}, // interface implementation registerEvent(target, type, capture) { // Nothing needs to be done here }, // interface implementation unregisterEvent(target, type, capture) { // Nothing needs to be done here }, __isReady: null, __isInitialized: null, __domReady: null, __loaded: null, __isUnloaded: null, /* --------------------------------------------------------------------------- USER ACCESS --------------------------------------------------------------------------- */ /** * Fires a global ready event. * */ __fireReady() { // Wrapper qxloader needed to be compatible with old generator if (!this.__isReady && this.__domReady && qx.$$loader.scriptLoaded) { // If qooxdoo is loaded within a frame in IE, the document is ready before // the "ready" listener can be added. To avoid any startup issue check // for the availability of the "ready" listener before firing the event. // So at last the native "load" will trigger the "ready" event. if (qx.core.Environment.get("engine.name") == "mshtml") { if (qx.event.Registration.hasListener(this._window, "ready")) { this.__isReady = true; // Fire user event qx.event.Registration.fireEvent(this._window, "ready"); } } else { this.__isReady = true; // Fire user event qx.event.Registration.fireEvent(this._window, "ready"); } } }, /** * Fires a global "appinitialized" event. * */ __fireAppInstanceInitialized() { this.__isInitialized = true; // Fire user event qx.event.Registration.fireEvent(this._window, "appinitialized"); }, /** * Whether the application is ready. * * @return {Boolean} ready status */ isApplicationReady() { return this.__isReady; }, /** * Whether the application is initialized * * @return {Boolean} initialization status */ isApplicationInitialized() { return this.__isInitialized; }, /* --------------------------------------------------------------------------- OBSERVER INIT/STOP --------------------------------------------------------------------------- */ /** * Initializes the native application event listeners. * */ _initObserver() { // in Firefox the loader script sets the ready state if ( qx.$$domReady || document.readyState == "complete" || document.readyState == "ready" ) { this.__domReady = true; this.__fireReady(); } else { this._onNativeLoadWrapped = qx.lang.Function.bind( this._onNativeLoad, this ); if ( qx.core.Environment.get("engine.name") == "gecko" || qx.core.Environment.get("engine.name") == "opera" || qx.core.Environment.get("engine.name") == "webkit" || (qx.core.Environment.get("engine.name") == "mshtml" && qx.core.Environment.get("browser.documentmode") > 8) ) { // Using native method supported by Mozilla, Webkit, Opera and IE >= 9 qx.bom.Event.addNativeListener( this._window, "DOMContentLoaded", this._onNativeLoadWrapped ); } else if (typeof document !== "undefined") { var self = this; // Continually check to see if the document is ready var timer = function () { try { // If IE is used, use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ document.documentElement.doScroll("left"); if (document.body) { self._onNativeLoadWrapped(); } } catch (error) { window.setTimeout(timer, 100); } }; timer(); } // Additional load listener as fallback qx.bom.Event.addNativeListener( this._window, "load", this._onNativeLoadWrapped ); } if ( qx.core.Environment.get("runtime.name") == "rhino" || qx.core.Environment.get("runtime.name") == "node.js" ) { return; } this._onNativeUnloadWrapped = qx.lang.Function.bind( this._onNativeUnload, this ); qx.bom.Event.addNativeListener( this._window, "unload", this._onNativeUnloadWrapped ); }, /** * Disconnect the native application event listeners. * */ _stopObserver() { if (this._onNativeLoadWrapped) { qx.bom.Event.removeNativeListener( this._window, "load", this._onNativeLoadWrapped ); } qx.bom.Event.removeNativeListener( this._window, "unload", this._onNativeUnloadWrapped ); this._onNativeLoadWrapped = null; this._onNativeUnloadWrapped = null; }, /* --------------------------------------------------------------------------- NATIVE LISTENER --------------------------------------------------------------------------- */ /** * When qx.globalErrorHandling is enabled the callback will observed */ _onNativeLoad() { var callback = qx.core.Environment.select("qx.globalErrorHandling", { true: qx.event.GlobalError.observeMethod(this.__onNativeLoadHandler), false: this.__onNativeLoadHandler }); callback.apply(this, arguments); }, /** * Event listener for native load event */ __onNativeLoadHandler() { this.__domReady = true; this.__fireReady(); }, /** * When qx.globalErrorHandling is enabled the callback will observed */ _onNativeUnload() { var callback = qx.core.Environment.select("qx.globalErrorHandling", { true: qx.event.GlobalError.observeMethod(this.__onNativeUnloadHandler), false: this.__onNativeUnloadHandler }); callback.apply(this, arguments); }, /** * Event listener for native unload event */ __onNativeUnloadHandler() { if (!this.__isUnloaded) { this.__isUnloaded = true; try { // Fire user event qx.event.Registration.fireEvent(this._window, "shutdown"); } catch (e) { // IE doesn't execute the "finally" block if no "catch" block is present throw e; } } } }, /* ***************************************************************************** DESTRUCTOR ***************************************************************************** */ destruct() { this._stopObserver(); this._window = null; }, /* ***************************************************************************** DEFER ***************************************************************************** */ defer(statics) { qx.event.Registration.addHandler(statics); } });