📄 application.js
字号:
/** * Informs the application of the modal state of a specific component. * When modal components are unregistered, this method must be executed * in order to avoid a memory leak. * * @param component the component * @param modal the modal state */ _setModal: function(component, modal) { Core.Arrays.remove(this._modalComponents, component); if (modal) { this._modalComponents.push(component); } // Auto-focus first component in modal context if component is currently focused component is not within modal context. if (this._modalComponents.length > 0 && this._focusedComponent) { var modalContextRoot = this.getModalContextRoot(); if (!modalContextRoot.isAncestorOf(this._focusedComponent)) { if (modalContextRoot.focusable) { this.setFocusedComponent(modalContextRoot); } else { this.setFocusedComponent(this.focusManager.findInParent(modalContextRoot, false)); } } } this.fireEvent({ source: this, type: "modal", modal: this._modalComponents.length > 0 }); }, /** * Sets the application style sheet. * * @param {Echo.StyleSheet} newValue the new style sheet */ setStyleSheet: function(newValue) { this._styleSheet = newValue; this.updateManager._processFullRefresh(); }, /** * Unregisters a component from the application. * This method is invoked when a component is removed from a hierarchy of * components registered with the application. * * @param {Echo.Component} component the component to remove */ _unregisterComponent: function(component) { this._idToComponentMap.remove(component.renderId); if (component.modalSupport) { this._setModal(component, false); } }});/** * Factory to create new instances of arbitrary components. This object is * used to instantiate new components during XML de-serialization. * @class */Echo.ComponentFactory = { /** * Mapping between type names and object constructors. */ _typeToConstructorMap: {}, /** * Creates a new instance of an arbitrary component. * * @param {String} typeName the type name of the component * @param {String} renderId the component render id * @return a newly instantiated component * @type Echo.Component */ newInstance: function(typeName, renderId) { var typeConstructor = this._typeToConstructorMap[typeName]; if (!typeConstructor) { throw new Error("Type not registered with ComponentFactory: " + typeName); } var component = new typeConstructor(); component.renderId = renderId; return component; }, /** * Returns the component constructor for the specified type. * * @param {String} typeName the type name * @return the component constructor * @type Function */ getConstructor: function(typeName) { return this._typeToConstructorMap[typeName]; }, /** * Determines the super type of a component, based on the type name of the component. * * @param {String} typeName the component type * @return the parent component type * @type String */ getSuperType: function(typeName) { var typeConstructor = this._typeToConstructorMap[typeName]; if (!typeConstructor) { // Type not registered, return Component base class name. return "Component"; } if (typeConstructor.$super) { return typeConstructor.$super.prototype.componentType; } else { return null; } }, /** * Registers a type name to a specific constructor. * * @param typeName the type name * @param typeConstructor the constructor */ registerType: function(typeName, typeConstructor) { if (this._typeToConstructorMap[typeName]) { throw new Error("Type already registered: " + typeName); } this._typeToConstructorMap[typeName] = typeConstructor; }};/** * Base class for components. * Derived classes should wishing to support hierarchal construction should provide constructors * with a first parameter name of 'properties' which is passed to the super-constructor. * In any case, the super-constructor must be invoked. * A component MUST have its componentType property set before it is used in a hierarchy. Failing to do so * will throw an exception and/or result in indeterminate behavior. * * @sp {#Color} background the background color * @sp {#Font} font the component font * @sp {#Color} foreground the foreground color * @sp layoutData layout data information, describing how the component should be rendered by its container * @event property An event fired when the a property of the component changes. The <code>propertyName</code> property * will specify the name of the changed property. The <code>oldValue</code> and <code>newValue</code> properties * (may) describe the previous and current states of the property, respectively. * @event init An event which is fired when the Component is added to a component hierarchy which is registered to an * application. The "application" property of the Component will be available when the event is fired. * @event dispose An event which is fired when the Component is about to be removed from a component hierarchy which is * registered to an application. The "application" property of the Component will be available when the event is fired. * @event parent An event which is fired when the Component's parent is changed. * @event children An event which is fired when a child is added to or removed from the Component. */Echo.Component = Core.extend({ $static: { /** * The next automatically assigned client render id. * @type Number */ _nextRenderId: 0 }, $load: function() { Echo.ComponentFactory.registerType("Component", this); }, $abstract: true, $virtual: { /** * Component type. * This value should be the fully-qualified name of the component, e.g. "Foo.ExampleComponent". * This property must be set by implementors in order for peer discovery to work properly. * @type String */ componentType: "Component", /** * Flag indicating whether or not the component is focusable. * @type Boolean */ focusable: false, /** * Returns the child component at the specified index after sorting the * children in the order which they should be focused. The default * implementation simply returns the same value as getComponent(). * Implementations should override this method when the natural order to * focus child components is different than their normal ordering (e.g., * when the component at index 1 is positioned above the component at * index 0). * * @param {Number} index the index of the child (in focus order) * @return the child component * @type Echo.Component */ getFocusComponent: function(index) { return this.children[index]; }, /** * Flag indicating whether component is rendered as a pane (pane components consume available height). * @type Boolean */ pane: false }, /** * Component layout direction. * @type Echo.LayoutDirection */ _layoutDirection: null, /** * Component locale. * @type String */ _locale: null, /** * The render id. * This value should be treated as read-only and immutable. * @type String */ renderId: null, /** * The parent component. * This value is read-only. * @type Echo.Component */ parent: null, /** * The registered application. * This value is read-only. * @type Echo.Application */ application: null, /** * Listener list. Lazily created. * @type Core.ListenerList */ _listenerList: null, /** * Referenced external style */ _style: null, /** * Assigned style name from application-level style sheet. * @type String */ _styleName: null, /** * Enabled state of the component (default true). * @type Boolean */ _enabled: true, /** * Array of child components. * This value is read-only. Modifying this array will result in undefined behavior. * @type Array */ children: null, /** * Internal style used to store properties set directly on component. */ _localStyle: null, /** * Creates a new Component. * The parent constructor MUST be invoked if it is overridden. This is accomplished by including the statement * "BaseComponent.call(this, properties)" in any derivative constructor, where "BaseComponent" is * class from which the component is immediately derived (which may or may not be Echo.Component itself). * * @param properties (Optional) associative mapping of initial property values (may be null) * By default, all properties will be placed into the local style, except for the following: * <ul> * <li><code>styleName</code> specifies the component stylesheet style name</li> * <li><code>style</code> specifies the referenced component style</li> * <li><code>renderId</code> specifies the render id</li> * <li><code>children</code> an array specifying the initial children of the component</li> * <li><code>events</code> an associative mapping between event names and listener methods</li> * </ul> */ $construct: function(properties) { this.children = []; this._localStyle = { }; if (properties) { for (var name in properties) { switch (name) { case "style": this._style = properties.style; break; case "styleName": this._styleName = properties.styleName; break; case "renderId": this.renderId = properties.renderId; break; case "children": for (var i = 0; i < properties.children.length; ++i) { this.add(properties.children[i]); } break; case "events": for (var eventType in properties.events) { this.addListener(eventType, properties.events[eventType]); } break; default: this._localStyle[name] = properties[name]; } } } }, /** * Adds a component as a child. * * @param {Echo.Component} component the component to add * @param {Number} index the (integer) index at which to add it (optional, omission * will cause component to be appended to end) */ add: function(component, index) { if (!(component instanceof Echo.Component)) { throw new Error("Cannot add child: specified component object is not derived from Echo.Component. " + "Parent: " + this + ", Child: " + component); } if (!component.componentType) { throw new Error("Cannot add child: specified component object does not have a componentType property. " + "Parent: " + this + ", Child: " + component); } if (component.parent) { component.parent.remove(component); } component.parent = this; if (index == null || index == this.children.length) { this.children.push(component); } else { this.children.splice(index, 0, component); } if (this.application) { component.register(this.application); this.application.notifyComponentUpdate(this, "children", null, component); } if (component._listenerList && component._listenerList.hasListeners("parent")) { component._listenerList.fireEvent({type: "parent", source: component, oldValue: null, newValue: this}); } if (this._listenerList && this._listenerList.hasListeners("children")) { this._listenerList.fireEvent({type: "children", source: this, add: component, index: index}); } }, /** * 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) { if (this._listenerList == null) { this._listenerList = new Core.ListenerList(); } this._listenerList.addListener(eventType, eventTarget); if (this.application) { this.application.notifyComponentUpdate(this, "listeners", null, eventType); } }, /** * 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); },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -