render.js

来自「echo3 很炫的ajax框架技术 js 演示demo ajax j2ee 里」· JavaScript 代码 · 共 713 行 · 第 1/2 页

JS
713
字号
/** * @namespace * Module for rendering state of application to DOM. * <ul> *  <li>Provides capability to process updates in Application UpdateManager, *   rendering state changes to the DOM.</li> *  <li>Provides component synchronization peer base class.</li> *  <li>Provides root component synchronization peer implementation.</li> *  <li>Provides rendering utilities for the core properties.</li> * </ul> *  * <h3>renderContext</h3> *  * <p>This object will add a <code>renderContext</code> property to all <code>Echo.Update.ComponentUpdate</code> * objects which are processed by it. *//** * Application rendering namespace. * @namespace */Echo.Render = {    /**     * Count of loaded/unloaded peers.  Used for testing purposes to ensure peers are not being leaked.     * @type Number     */    _loadedPeerCount: 0,    /**     * Next sequentially assigned unique peer identifier.     * @type Number     */    _nextPeerId: 0,        /**     * Mapping between component type names and instantiable peer classes.     */    _peers: {},        /**     * Map containing removed components.  Maps component ids to removed components.     * Created and destroyed during each render.     */    _disposedComponents: null,        /**     * An array sorting implementation to organize an array by component depth.     * @see Array#sort     */    _componentDepthArraySort: function(a, b) {        return Echo.Render._getComponentDepth(a.parent) - Echo.Render._getComponentDepth(b.parent);    },        /**     * Recursively invokes renderDisplay() method on a sub-hierarchy of the     * component hierarchy.  If a peer does not provide a renderDisplay() implementation,     * it is skipped (although its descendants will NOT be skipped).     *      * @param {Echo.Component} the root component of the sub-hierarchy on which renderDisplay() should be invoked     * @param {Boolean} includeSelf flag indicating whether renderDisplay() should be invoked on the     *        specified component (if false, it will only be invoked on child components)     */    _doRenderDisplay: function(component, includeSelf) {        if (includeSelf) {            Echo.Render._doRenderDisplayImpl(component);        } else {            for (var i = 0; i < component.children.length; ++i) {                Echo.Render._doRenderDisplayImpl(component.children[i]);            }        }    },        /**     * Recursive work method for _doRenderDisplay().       *      * @param {Echo.Component} component the component on which to invoke renderDisplay()     */    _doRenderDisplayImpl: function(component) {        if (component.peer) {            // components that are present on the client, but are not rendered (lazy rendered as in tree),             // have no peer installed.            if (component.peer.renderDisplay) {                component.peer.renderDisplay();            }                        for (var i = 0; i < component.children.length; ++i) {                Echo.Render._doRenderDisplayImpl(component.children[i]);            }        }    },        /**     * Returns the depth of a specific component in the hierarchy.     * The root component is at depth 0, its immediate children are     * at depth 1, their children are at depth 2, and so on.     *     * @param {Echo.Component} component the component whose depth is to be calculated     * @return the depth of the component     * @type Number     */    _getComponentDepth: function(component) {        var depth = -1;        while (component != null) {            component = component.parent;            ++depth;        }        return depth;    },        /**     * Creates a component synchronization peer for a component.     * The peer will be stored in the "peer" property of the component.     * The client will be stored in the "client" property of the component.     *      * @param {Echo.Client} client the relevant Client     * @param {Echo.Component} component the component     */    _loadPeer: function(client, component) {        if (component.peer) {            // If peer already loaded, do nothing.            return;        }                var peerClass = Echo.Render._peers[component.componentType];                if (!peerClass) {            throw new Error("Peer not found for: " + component.componentType);        }                ++this._loadedPeerCount;                component.peer = new peerClass();        component.peer._peerId = this._nextPeerId++;        component.peer.component = component;        component.peer.client = client;    },        /**     * Notifies child components that the parent component has been drawn     * or resized.  At this point the parent component is on the screen     * (the parent element is part of the DOM hierarchy).     * Child components (and their descendants) will be notified by having      * their renderDisplay() implementations invoked.     * Note that the parent WILL NOT have its renderDisplay() method     * invoked.     * <p>     * If your component requires virtual positioning (for IE6) you should invoke     * this method after informing the virtual positioning system to recalculate     * the size of your component.     *      * @param {Echo.Component} parent the component whose size changed     */    notifyResize: function(parent) {        Echo.Render._doRenderDisplay(parent, false);    },        /**     * Invokes renderDispose() on all removed children and descendants found in the specified update.     *      * @param {Echo.Update.ComponentUpdate} update the update     */    _processDispose: function(update) {        var i, components = update.getRemovedDescendants();        if (components) {            for (i = 0; i < components.length; ++i) {                Echo.Render._renderComponentDisposeImpl(update, components[i]);            }        }        components = update.getRemovedChildren();        if (components) {            for (i = 0; i < components.length; ++i) {                Echo.Render._renderComponentDisposeImpl(update, components[i]);            }        }    },        /**     * Processes all pending updates in the client's application's update manager.     *      * @param {Echo.Client} client the client     */    processUpdates: function(client) {        var updateManager = client.application.updateManager;                // Do nothing if no updates exist.        if (!updateManager.hasUpdates()) {            return;        }                // Create map to contain removed components (for peer unloading).        Echo.Render._disposedComponents = {};                // Retrieve updates, sorting by depth in hierarchy.  This will ensure that higher        // level updates have a chance to execute first, in case they null out lower-level        // updates if they require re-rendering their descendants.        var updates = updateManager.getUpdates();        updates.sort(Echo.Render._componentDepthArraySort);                var peer, i, j;            // Load peers for any new root components being updated.        for (i = 0; i < updates.length; ++i) {            updates[i].renderContext = {};                    peer = updates[i].parent.peer;            if (peer == null && updates[i].parent.componentType == "Root") {                Echo.Render._loadPeer(client, updates[i].parent);            }        }            // Remove Phase: Invoke renderDispose on all updates.        for (i = updates.length - 1; i >= 0; --i) {            if (updates[i] == null) {                // Skip removed updates.                continue;            }            peer = updates[i].parent.peer;            Echo.Render._processDispose(updates[i]);        }                // Profiling: Mark completion of remove phase.         if (Echo.Client.profilingTimer) {            Echo.Client.profilingTimer.mark("rem");        }                // Update Phase: Invoke renderUpdate on all updates.        for (i = 0; i < updates.length; ++i) {            if (updates[i] == null) {                // The update has been removed, skip it.                continue;            }                        // Obtain component synchronization peer.            peer = updates[i].parent.peer;                        // Perform update by invoking peer's renderUpdate() method.            var fullRender = peer.renderUpdate(updates[i]);                        // If the update required re-rendering descendants of the updated component,            // null-out any pending updates to descendant components.            if (fullRender) {                for (j = i + 1; j < updates.length; ++j) {                    if (updates[j] != null && updates[i].parent.isAncestorOf(updates[j].parent)) {                        updates[j] = null;                    }                }            }            // Invoke _setPeerDisposedState() to ensure that peer is marked as non-disposed.            // (A full-re-render may have invoked renderComponentDispose()).            Echo.Render._setPeerDisposedState(updates[i].parent, false);        }                // Profiling: Mark completion of update phase.        if (Echo.Client.profilingTimer) {            Echo.Client.profilingTimer.mark("up");        }                // Display Phase: Invoke renderDisplay on all updates.        // The "displayed" array holds component who have already had renderDisplay() invoked on themselves (and their descendants).        // This is done to avoid invoking renderDisplay() multiple times on a single component during a single rendering.        var displayed = [];        for (i = 0; i < updates.length; ++i) {            if (updates[i] == null) {                // Skip removed updates.                continue;            }                        // Determine if component hierarchy has already had renderDisplay() invoked, skipping to next update if necessary.            var cancelDisplay = false;            for (j = 0; j < displayed.length; ++j) {                if (displayed[j].isAncestorOf(updates[i].parent)) {                    cancelDisplay = true;                    break;                }            }            if (cancelDisplay) {                continue;            }                        if (updates[i].renderContext.displayRequired) {                // The renderContext has specified only certain child components should have their                // renderDisplay() methods invoked.                for (j = 0; j < updates[i].renderContext.displayRequired.length; ++j) {                    displayed.push(updates[i].renderContext.displayRequired[j]);                    Echo.Render._doRenderDisplay(updates[i].renderContext.displayRequired[j], true);                }            } else {                displayed.push(updates[i].parent);                Echo.Render._doRenderDisplay(updates[i].parent, true);            }        }            // Profiling: Mark completion of display phase.        if (Echo.Client.profilingTimer) {            Echo.Client.profilingTimer.mark("disp");        }            // Unload peers for truly removed components, destroy mapping.        for (var peerId in Echo.Render._disposedComponents) {            var component = Echo.Render._disposedComponents[peerId];            Echo.Render._unloadPeer(component);        }        // Clear disposed component list.        Echo.Render._disposedComponents = null;                // Inform UpdateManager that all updates have been completed.        updateManager.purge();                // Perform focus update.        Echo.Render.updateFocus(client);    },        /**     * Registers a component type name with an instantiable peer class.     * Components of the specified type name will be assigned new instances of the peer class     * when rendered for the first time.     *      * @param {String} componentName the component type name     * @param {Function} peerObject the peer class object     */    registerPeer: function(componentName, peerObject) {        if (this._peers[componentName]) {            throw new Error("Peer already registered: " + componentName);        }        this._peers[componentName] = peerObject;    },        /**     * Renders a new component inside of a DOM element.     * This method should be called by container components in order to render their children.     *      * @param {Echo.Update.ComponentUpdate} update the relevant ComponentUpdate     * @param {Echo.Component} component the component to add     * @param {Element} parentElement the DOM element to which the rendered component should be added     */    renderComponentAdd: function(update, component, parentElement) {        if (!component.parent || !component.parent.peer || !component.parent.peer.client) {            throw new Error("Cannot find reference to the Client with which this component should be associated: " +                    "cannot load peer.  This is due to the component's parent's peer not being associated with a Client. " +                    "Component = " + component);        }            Echo.Render._loadPeer(component.parent.peer.client, component);        Echo.Render._setPeerDisposedState(component, false);        component.peer.renderAdd(update, parentElement);    },        /**     * Manually invokes renderDisplay on a component (and its descendants) that was added to the     * hierarchy outside of processUpdates().  This method is only used in special cases,     * e.g., by in the case of Application Rendered Components that need to render children.     *      * @param {Echo.Component} parent the parent component of the sub-hierarchy on which renderDisplay() should     *        be invoked (note that renderDisplay WILL be invoked on the parent as well      *        as its descendants)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?