📄 client.js
字号:
/** * Abstract base class for Echo clients. * @namespace */Echo.Client = Core.extend({ $static: { /** * Global array containing all active client instances in the current browser window. * @type Array */ _activeClients: [], /** * Global listener to respond to resizing of browser window. * Invokes _windowResizeListener() method on all active clients. * * @param e the DOM resize event */ _globalWindowResizeListener: function(e) { for (var i = 0; i < Echo.Client._activeClients.length; ++i) { Echo.Client._activeClients[i]._windowResizeListener(e); } } }, $load: function() { // Register resize listener on containing window one time. Core.Web.DOM.addEventListener(window, "resize", this._globalWindowResizeListener, false); }, /** * Flag indicating the user interface should be rendered in design-mode, where all rendered component elements are * assigned an id. * @type Boolean */ designMode: false, /** * The root DOM element in which the application is contained. * @type Element */ domainElement: null, /** * The application being managed by this client. * @type Echo.Application */ application: null, /** * Id of last issued input restriction id (incremented to deliver unique identifiers). * @type Number */ _lastInputRestrictionId: 0, /** * Number of currently registered input restrictions. * @type Number */ _inputRestrictionCount: 0, /** * Echo.Component renderId-to-restriction listener mapping. */ _inputRestrictionListeners: null, /** * Id (String) map containing input restrictions. * Values are booleans, true indicating property updates are NOT restricted, and false * indicated all updates are restricted. */ _inputRescriptionMap: null, /** * Method reference to this._processKeyPressRef(). * @type Function */ _processKeyPressRef: null, /** * Method reference to this._processApplicationFocus(). * @type Function */ _processApplicationFocusRef: null, /** * The parent client. * @type Echo.Client */ parent: null, /** * Wait indicator. * @type Echo.Client.WaitIndicator */ _waitIndicator: null, /** * Restriction time before raising wait indicator, in milliseconds. * @type Number */ _preWaitIndicatorDelay: 500, /** * Runnable that will trigger initialization of wait indicator. * @type Core.Web.Scheduler.Runnable */ _waitIndicatorRunnable: null, /** * Creates a new Client instance. Derived classes must invoke. */ $construct: function() { this._inputRestrictionMap = { }; this._processKeyPressRef = Core.method(this, this._processKeyPress); this._processApplicationFocusRef = Core.method(this, this._processApplicationFocus); this._waitIndicator = new Echo.Client.DefaultWaitIndicator(); this._waitIndicatorRunnable = new Core.Web.Scheduler.MethodRunnable(Core.method(this, this._waitIndicatorActivate), this._preWaitIndicatorDelay, false); }, $abstract: true, $virtual: { /** * Returns the URL of a resource based on package name / * resource name information. * Derived implementations should generally override this * method, and delegate to superclass if they are unable * to provide a resource for a specific URL. * Default implementation delegates to parent client * (if one is present) or otherwise returns null. * * @param {String} packageName the package name in which the resource is contained * @param {String} resourceName the resource name * @return the full URL * @type String */ getResourceUrl: function(packageName, resourceName) { if (this.parent) { return this.parent.getResourceUrl(packageName, resourceName); } else { return null; } }, /** * Determines if the specified component and containing application is ready to receive input. * This method should be overridden by client implementations as needed, returning the value * from this implementation if the client has no other reason to disallow input. * * @param {Echo.Component} component optional parameter indicating the component to query (if omitted, only the * application's readiness state will be investigated) * @return true if the application/component are ready to receive input * @type Boolean */ verifyInput: function(component) { // Check for input restrictions. if (this._inputRestrictionCount !== 0) { return false; } if (component) { return component.isActive(); } else { return this.application.isActive(); } }, /** * Default dispose implementation. * Invokes configure(null, null) to deconfigure the client. */ dispose: function() { this.configure(null, null); } }, /** * Configures/Deconfigures the client. This method must be invoked * with the supported application/containing domain element before * the client is used, and invoked with null values before it is * disposed (in order to clean up resources). * * @param {Echo.Application} application the application the client will support (if configuring) * or null (if deconfiguring) * @param {Element} domainElement the DOM element into which the client will be rendered (if configuring), * or null (if deconfiguring) */ configure: function(application, domainElement) { if (this.application) { // Deconfigure current application if one is configured. Core.Arrays.remove(Echo.Client._activeClients, this); Core.Web.Event.remove(this.domainElement, Core.Web.Env.QUIRK_IE_KEY_DOWN_EVENT_REPEAT ? "keydown" : "keypress", this._processKeyPressRef, false); this.application.removeListener("focus", this._processApplicationFocusRef); this.application.doDispose(); this.application.client = null; } // Update state. this.application = application; this.domainElement = domainElement; if (this.application) { // Configure new application if being set. this.application.client = this; this.application.doInit(); this.application.addListener("focus", this._processApplicationFocusRef); Core.Web.Event.add(this.domainElement, Core.Web.Env.QUIRK_IE_KEY_DOWN_EVENT_REPEAT ? "keydown" : "keypress", this._processKeyPressRef, false); Echo.Client._activeClients.push(this); } }, /** * Registers a new input restriction. Input will be restricted until this and all other * input restrictions are removed. * * @return a handle identifier for the input restriction, which will be used to unregister * the restriction by invoking removeInputRestriction() */ createInputRestriction: function() { Core.Web.Scheduler.add(this._waitIndicatorRunnable); var id = (++this._lastInputRestrictionId).toString(); ++this._inputRestrictionCount; this._inputRestrictionMap[id] = true; return id; }, /** * Loads required libraries and then executes a function, adding input restrictions while the libaries are being loaded. * * @param {Array} requiredLibraries the URLs of the libraries which must be loaded before the function can execute * @param {Function} f the function to execute */ exec: function(requiredLibraries, f) { var restriction = this.createInputRestriction(); Core.Web.Library.exec(requiredLibraries, Core.method(this, function() { this.removeInputRestriction(restriction); f(); })); }, /** * Handles an application failure, refusing future input and displaying an error message over the entirety of the domain * element. * * @param {String} msg the message to display (a generic message will be used if omitted) */ fail: function(msg) { // Block future input. this.createInputRestriction(false); // Default message. msg = msg || "This application has been stopped due to an error. Press the reload or refresh button."; // Darken screen. if (!Core.Web.Env.NOT_SUPPORTED_CSS_OPACITY) { var blackoutDiv = document.createElement("div"); blackoutDiv.style.cssText = "position:absolute;z-index:32766;width:100%;height:100%;background-color:#000000;" + "opacity:0.75;"; this.domainElement.appendChild(blackoutDiv); } // Display fail message. var div = document.createElement("div"); div.style.cssText = "position:absolute;z-index:32767;width:100%;height:100%;"; this.domainElement.appendChild(div); var msgDiv = document.createElement("div"); msgDiv.style.cssText = "border:#5f1f1f outset 1px;background-color:#5f1f1f;color:#ffffff;padding:2px 10px;"; msgDiv.appendChild(document.createTextNode(msg));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -