📄 application.js
字号:
while (this.children.length > 0) { this.remove(this.children.length - 1); } }, /** * 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) { if (this._listenerList == null) { return; } this._listenerList.removeListener(eventType, eventTarget); if (this.application) { this.application.notifyComponentUpdate(this, "listeners", eventType, null); } }, /** * Sets the value of a property in the internal style. * * @param {String} name the name of the property * @param value the new value of the property */ set: function(name, newValue) { var oldValue = this._localStyle[name]; if (oldValue === newValue) { return; } this._localStyle[name] = newValue; if (this._listenerList && this._listenerList.hasListeners("property")) { this._listenerList.fireEvent({type: "property", source: this, propertyName: name, oldValue: oldValue, newValue: newValue}); } if (this.application) { this.application.notifyComponentUpdate(this, name, oldValue, newValue); } }, /** * Sets the enabled state of the component. * * @param newValue the new enabled state */ setEnabled: function(newValue) { var oldValue = this._enabled; this._enabled = newValue; if (this.application) { this.application.notifyComponentUpdate(this, "enabled", oldValue, newValue); } }, /** * Sets the value of an indexed property in the internal style. * * @param {String} name the name of the property * @param {Number} index the index of the property * @param newValue the new value of the property */ setIndex: function(name, index, newValue) { var valueArray = this._localStyle[name]; var oldValue = null; if (valueArray) { oldValue = valueArray[index]; if (oldValue === newValue) { return; } } else { valueArray = []; this._localStyle[name] = valueArray; } valueArray[index] = newValue; if (this.application) { this.application.notifyComponentUpdate(this, name, oldValue, newValue); } if (this._listenerList && this._listenerList.hasListeners("property")) { this._listenerList.fireEvent({type: "property", source: this, propertyName: name, index: index, oldValue: oldValue, newValue: newValue}); } }, /** * Sets a component-specific layout direction. * Note that in most cases it is preferable to set the layout direction of the Application, * rather than individual components. * * @param {Echo.LayoutDirection} newValue the new layout direction */ setLayoutDirection: function(newValue) { var oldValue = this._layoutDirection; this._layoutDirection = newValue; if (this.application) { this.application.notifyComponentUpdate(this, "layoutDirection", oldValue, newValue); } }, /** * Sets a component-specific locale. * Note that in most cases it is preferable to set the locale of the Application, * rather than individual components. * * @param {String} newValue the new layout direction */ setLocale: function(newValue) { var oldValue = this._locale; this._locale = newValue; if (this.application) { this.application.notifyComponentUpdate(this, "locale", oldValue, newValue); } }, /** * Sets the style of the component. * * @param newValue the new style */ setStyle: function(newValue) { var oldValue = this._style; this._style = newValue; if (this.application) { this.application.notifyComponentUpdate(this, "style", oldValue, newValue); } }, /** * Sets the name of the style (from the application's style sheet) * assigned to this component. * * @param {String} newValue the style name */ setStyleName: function(newValue) { var oldValue = this._styleName; this._styleName = newValue; if (this.application) { this.application.notifyComponentUpdate(this, "styleName", oldValue, newValue); } }, /** * Returns a string representation of the component (default implementation). * * @param {Boolean} longFormat an optional flag specifying whether all information about * the component should be displayed (e.g., property values) * @return a string representation of the component * @type String */ toString: function(longFormat) { var out = this.renderId + "/" + this.componentType; if (longFormat) { out += "\n"; var componentCount = this.getComponentCount(); out += this.renderId + "/properties:" + this._localStyle + "\n"; for (var i = 0; i < componentCount; ++i) { var component = this.getComponent(i); out += this.renderId + "/child:" + component.renderId + "\n"; out += component.toString(true); } } return out; }});/** * Provides focus management tools for an application. */Echo.FocusManager = Core.extend({ /** * The managed application. * @type Echo.Application */ _application: null, /** * Focus management handler for a specific application instance. * One FocusManager is created for each application. * * @param {Echo.Application} the managed application */ $construct: function(application) { this._application = application; }, /** * Searches the component hierarchy for the next component that should * be focused (based on the currently focused component). * Container components are queried to determine the order in which their * children should naturally be focused (certain components, e.g., SplitPanes, * will have a child focus order that may be different from the order of their * children). * This search is depth first. * * Search order (FORWARD): * * (Start on Component) * First Child, next sibling, parent * * Search order (REVERSE): * Last Child, previous sibling, parent * * @return the Component which should be focused * @type Echo.Component */ find: function(component, reverse) { if (!component) { component = this._application.getFocusedComponent(); if (!component) { component = this._application.rootComponent; } } /** The component which is currently focused by the application. */ var originComponent = component; /** An associative array containing the ids of all previously visited components. */ var visitedComponents = { }; /** The value of 'component' on the previous iteration. */ var lastComponent = null; while (true) { /** The candidate next component to be focused */ var nextComponent = null, componentIndex; if ((reverse && component == originComponent) || (lastComponent && lastComponent.parent == component)) { // Searching in reverse on origin component (OR) Previously moved up: do not move down. } else { var componentCount = component.getComponentCount(); if (componentCount > 0) { // Attempt to move down. // Next component is first child (searching forward) or last child (searching reverse). nextComponent = component.getComponent(reverse ? componentCount - 1 : 0); if (visitedComponents[nextComponent.renderId]) { // Already visited children, cancel the move. nextComponent = null; } } } if (nextComponent == null) { // Attempt to move to next/previous sibling. if (component.parent) { // Get previous sibling. if (reverse) { componentIndex = component.parent.indexOf(component); if (componentIndex > 0) { nextComponent = component.parent.getComponent(componentIndex - 1); } } else { componentIndex = component.parent.indexOf(component); if (componentIndex < component.parent.getComponentCount() - 1) { nextComponent = component.parent.getComponent(componentIndex + 1); } } } } if (nextComponent == null) { // Attempt to move up. nextComponent = component.parent; } if (nextComponent == null) { return null; } lastComponent = component; component = nextComponent; visitedComponents[component.renderId] = true; if (component != originComponent && component.isActive() && component.focusable) { return component; } } }, /** * Finds next (or previous) focusable descendant of a parent component. * This method requires that the application's currently focused component * be a descendant of the specified parent component. The search will * be limited to descendants of the parent component, i.e., if a suitable descendant * component cannot be found, null will be returned. * * The <code>minimumDistance</code> property may be used to skip a number of siblings. * This is used by components such as "Grid" which may want to find a focusable component * in the next row, skipping over all columns of the current row. * If omitted the default value of this property is 1. As an example, a value of 2 * would skip the immediately adjacent sibling of the current focused component. * * @param {Echo.Component} parentComponent the parent component to search * @param {Boolean} reverse the search direction, false indicating to search forward, true * indicating reverse * @param {Number} minimumDistance the fewest number of lateral focus moves to make before * returning a focusable component (optional, default value of 1) * @return the focusable descendant, or null if one cannot be found * @type Echo.Component */ findInParent: function(parentComponent, reverse, minimumDistance) { if (!minimumDistance) { minimumDistance = 1; } var focusedComponent = this._application.getFocusedComponent(); var focusedIndex = this._getDescendantIndex(parentComponent, focusedComponent); if (focusedIndex == -1) { return null; } var componentIndex = focusedIndex; var component = focusedComponent; do { component = this.find(component, reverse); if (component == null) { return null; } componentIndex = this._getDescendantIndex(parentComponent, component); } while (Math.abs(componentIndex - focusedIndex) < minimumDistance && component != focusedComponent); if (component == focusedComponent) { // Search wrapped, only one focusable component. return null; } this._application.setFocusedComponent(component); return component; }, /** * Determines the index of the child of <code>parent</code> in which * <code>descendant</code> is contained. * * @param {Echo.Component} parent the parent component * @param {Echo.Component} descendant the descendant component * @return the descendant index, or -1 if the component is not a descendant of <code>parent</code> * @type Number */ _getDescendantIndex: function(parent, descendant) { while (descendant.parent != parent && descendant.parent != null) { descendant = descendant.parent; } if (descendant.parent == null) { return -1; } return parent.indexOf(descendant); }});/** * Describes the layout direction of text and content to provide support * for bidirectional localization. */Echo.LayoutDirection = Core.extend({ /** * Flag indicating whether layout direction is left-to-right. * @type Boolean */ _ltr: false, /** * LayoutDirection property. Do not instantiate, use LTR/RTL constants. * * @param {Boolean} ltr true if the layout direction is left-to-right */ $construct: function(ltr) { this._ltr = ltr; }, /** * Determines if the layout direction is left-to-right. * * @return true if the layout direction is left-to-right * @type Boolean */ isLeftToRight: function() { return this._ltr; }});/** * Global instance representing a left-to-right layout direction. * @type Echo.LayoutDirection * @final */Echo.LayoutDirection.LTR = new Echo.LayoutDirection(true);/** * Global instance representing a right-to-left layout direction.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -