📄 application.js
字号:
/** * @fileoverview * Application framework main module. * Requires Core. *//** * Main namespace of Echo framework. * @namespace */Echo = { };/** * Representation of a single application instance. * Derived objects must invoke constructor with root component id. * * @event componentUpdate An event fired when any component within the application is updated. * Listening for this event may degrade the performance of an application, due to the * frequency with which it will be fired. * @event focus An event fired when the focused component of the application changes. * @event modal An event fired when the modal state of the application changes. */Echo.Application = Core.extend({ $static: { /** * Next unique identifier. */ _nextUid: 1, /** * Generates a unique identifier. Identifiers are unique for the duration of the existence of this namespace. */ generateUid: function() { return this._nextUid++; } }, $abstract: true, $virtual: { /** * Performs application initialization operations. This method should be provided by an application implementation * if required. The superclass' <code>init()</code> method should always be invoked out of convention. * The <code>client</code> property will be available. */ init: function() { }, /** * Performs application disposal/resource cleanup operations. This method should be provided by an application implementation * if required. The superclass' <code>dispose()</code> method should always be invoked out of convention. * The <code>client</code> property will be available. */ dispose: function() { } }, /** * The client engine hosting the application. * This property is provided solely for use by the application itself, it is not (and may not be) used internally for any * purpose. * @type Object */ client: null, /** * Mapping between component ids and component instances. * @type Core.Arrays.LargeMap */ _idToComponentMap: null, /** * ListenerList instance for application-level events. * @type Core.ListenerList */ _listenerList: null, /** * Default application locale. * @type String */ _locale: null, /** * Array of modal components. * This value is read-only. * @type Array */ _modalComponents: null, /** * Displayed style sheet. * * @type Echo.StyleSheet */ _styleSheet: null, /** * Currently focused component. * @type Echo.Component */ _focusedComponent: null, /** * Root component instance. * This value is read-only. * @type Echo.Component */ rootComponent: null, /** * UpdateManager instance monitoring changes to the application for redraws. * @type Echo.Update.Manager */ updateManager: null, /** * FocusManager instance handling application focus behavior. * @type Echo.FocusManager */ focusManager: null, /** * Creates a new application instance. * @constructor */ $construct: function() { this._idToComponentMap = new Core.Arrays.LargeMap(); this._listenerList = new Core.ListenerList(); this.rootComponent = new Echo.Component(); this.rootComponent.componentType = "Root"; this.rootComponent.register(this); this._modalComponents = []; this.updateManager = new Echo.Update.Manager(this); this.focusManager = new Echo.FocusManager(this); }, /** * Adds an arbitrary event listener. * * @param {String} eventType the event type name * @param {Function} eventTarget the method to invoke when the event occurs * (the event will be passed as the single argument) */ addListener: function(eventType, eventTarget) { this._listenerList.addListener(eventType, eventTarget); }, /** * Invoked by application container to dispose of the application. * Invokes application-overridable <code>dispose()</code> method. * Once invoked, the application will no longer function and cannot be used again. * This method will free any resources allocated by the application. */ doDispose: function() { this.updateManager.dispose(); this.dispose(); }, /** * Invoked by application container to initialize of the application. * Invokes application-overridable <code>init()</code> method. */ doInit: function() { this.init(); }, /** * Recursively determines the current root component of the modal context. * * @param {Echo.Component} searchComponent (optional) the component from which to search * (this parameter is provided when recursively searching, if omitted the sear * will begin at the root component of the application). * @return the current modal context root component */ _findModalContextRoot: function(searchComponent) { searchComponent = searchComponent ? searchComponent : this.rootComponent; for (var i = searchComponent.children.length - 1; i >= 0; --i) { var foundComponent = this._findModalContextRoot(searchComponent.children[i]); if (foundComponent) { return foundComponent; } } if (searchComponent.modalSupport && searchComponent.get("modal")) { return searchComponent; } return null; }, /** * Provides notification of an arbitrary event. * Listeners will be notified based on the event's type property. * * @param event the event to fire */ fireEvent: function(event) { if (this._listenerList == null) { return; } this._listenerList.fireEvent(event); }, /** * Focuses the previous/next component based on the currently focused component. * * @param {Boolean} reverse false to focus the next component, true to focus the * previous component */ focusNext: function(reverse) { var focusedComponent = this.focusManager.find(null, reverse); if (focusedComponent != null) { this.setFocusedComponent(focusedComponent); } }, /** * Retrieves the registered component with the specified render id. * * @param {String} renderId the render id * @return the component * @type Echo.Component */ getComponentByRenderId: function(renderId) { return this._idToComponentMap.map[renderId]; }, /** * Returns the focused component. * * @return the focused component * @type Echo.Component */ getFocusedComponent: function() { return this._focusedComponent; }, /** * Returns the default layout direction of the application. * * @return the default layout direction * @type Echo.LayoutDirection */ getLayoutDirection: function() { return this._layoutDirection ? this._layoutDirection : Echo.LayoutDirection.LTR; }, /** * Returns the default locale of the application. * * @return the default locale * @type String */ getLocale: function() { return this._locale; }, /** * Returns the root component of the modal context. * * @return the root component of the modal context * @type Echo.Component */ getModalContextRoot: function() { if (this._modalComponents.length === 0) { return null; } else if (this._modalComponents.length == 1) { return this._modalComponents[0]; } return this._findModalContextRoot(); }, /** * Returns the application style sheet. * * @return the application style sheet * @type Echo.StyleSheet */ getStyleSheet: function() { return this._styleSheet; }, /** * Returns the active state of the application. * * @return the active state of the application, a value of * true indicating the application is ready for user * input, a value of false indicating otherwise * @type Boolean */ isActive: function() { return true; }, /** * Notifies the application of an update to a component. * Fires a <code>componentUpdate</code> event. * * @param {Echo.Component} parent the parent component * @param {String} propertyName the updated property * @param oldValue the previous property value * @param newValue the new property value */ notifyComponentUpdate: function(parent, propertyName, oldValue, newValue) { if (parent.modalSupport && propertyName == "modal") { this._setModal(parent, newValue); } if (this._listenerList.hasListeners("componentUpdate")) { this._listenerList.fireEvent({type: "componentUpdate", parent: parent, propertyName: propertyName, oldValue: oldValue, newValue: newValue}); } this.updateManager._processComponentUpdate(parent, propertyName, oldValue, newValue); }, /** * Registers a component with the application. * Invoked when a component is added to a hierarchy of * components that is registered with the application. * * @param {Echo.Component} component the component to register */ _registerComponent: function(component) { if (this._idToComponentMap.map[component.renderId]) { throw new Error("Component already exists with id: " + component.renderId); } this._idToComponentMap.map[component.renderId] = component; if (component.modalSupport && component.get("modal")) { this._setModal(component, true); } }, /** * Removes an arbitrary event listener. * * @param {String} eventType the event type name * @param {Function} eventTarget the method to invoke when the event occurs * (the event will be passed as the single argument) */ removeListener: function(eventType, eventTarget) { this._listenerList.removeListener(eventType, eventTarget); }, /** * Sets the focused component. * A "focus" event is fired to application listeners to inform them of the change. * * @param {Echo.Component} newValue the new focused component */ setFocusedComponent: function(newValue) { // If required, find focusable parent containing 'newValue'. while (newValue != null && !newValue.focusable) { newValue = newValue.parent; } // Verify new focused component is within modal context. if (this._modalComponents.length > 0) { var modalContextRoot = this.getModalContextRoot(); if (!modalContextRoot.isAncestorOf(newValue)) { // Reject request to focus component outside of modal context. return; } } if (this._focusedComponent == newValue) { return; } this._focusedComponent = newValue; this._listenerList.fireEvent({type: "focus", source: this}); }, /** * Sets the application default layout direction. * * @param {Echo.LayoutDirection} newValue the new layout direction */ setLayoutDirection: function(newValue) { this._layoutDirection = newValue; this.updateManager._processFullRefresh(); }, /** * Sets the application default locale. * * @param {String} newValue the new locale */ setLocale: function(newValue) { this._locale = newValue; this.updateManager._processFullRefresh(); },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -