📄 sync.arraycontainer.js
字号:
/** * Abstract base class for column/row peers. */Echo.Sync.ArrayContainer = Core.extend(Echo.Render.ComponentSync, { $abstract: { /** * The DOM element name of child container cells. * @type String */ cellElementNodeName: null, /** * Abstract method which renders layout data on child cell element. * * @param {Echo.Component} child the child component * @param {Element} the DOM element containing the child */ renderChildLayoutData: function(child, cellElement) { } }, $virtual: { /** * The key code which should move focus to the previous child cell. * @type Number */ prevFocusKey: null, /** * The Echo.Render.ComponentSync focus flag indicating which keys should trigger focus changes to the previous child. * @type Boolean */ prevFocusFlag: null, /** * The key code which should move focus to the next child cell. * @type Number */ nextFocusKey: null, /** * The Echo.Render.ComponentSync focus flag indicating which keys should trigger focus changes to the next child. * @type Boolean */ nextFocusFlag: null, /** * Flag indicating whether focus key should be inverted when the component is rendered with an RTL layout direction. * @type Boolean */ invertFocusRtl: false }, /** * The root DOM element of the rendered array container. * @type Element */ element: null, /** * The DOM element to which child elements should be added. May be equivalent to <code>element</code>. * @type Element */ containerElement: null, /** * Prototype Element to be cloned and added between cells of the array container. * * @type Element */ spacingPrototype: null, /** * Number of pixels to be rendered as spacing between child cells of the container. * @type Number */ cellSpacing: null, /** * Mapping between child render ids and child container cell elements. */ _childIdToElementMap: null, /** * Processes a key press event. Provides support for adjusting focus via arrow keys. * * @param e the event */ processKeyPress: function(e) { if (!this.client) { return; } switch (e.keyCode) { case this.prevFocusKey: case this.nextFocusKey: var focusPrevious = e.keyCode == this.prevFocusKey; if (this.invertFocusRtl && !this.component.getRenderLayoutDirection().isLeftToRight()) { focusPrevious = !focusPrevious; } var focusedComponent = this.client.application.getFocusedComponent(); if (focusedComponent && focusedComponent.peer && focusedComponent.peer.getFocusFlags) { var focusFlags = focusedComponent.peer.getFocusFlags(); if ((focusPrevious && focusFlags & this.prevFocusFlag) || (!focusPrevious && focusFlags & this.nextFocusFlag)) { var focusChild = this.client.application.focusManager.findInParent(this.component, focusPrevious); if (focusChild) { this.client.application.setFocusedComponent(focusChild); Core.Web.DOM.preventEventDefault(e); return false; } } } break; } return true; }, /** * Renders the specified child to the containerElement. * * @param {Echo.Update.ComponentUpdate} the update * @param {Echo.Component} the child component * @param {Number} index the index of the child within the parent */ _renderAddChild: function(update, child, index) { var cellElement = document.createElement(this.cellElementNodeName); this._childIdToElementMap[child.renderId] = cellElement; Echo.Render.renderComponentAdd(update, child, cellElement); this.renderChildLayoutData(child, cellElement); if (index != null) { var currentChildCount; if (this.containerElement.childNodes.length >= 3 && this.cellSpacing) { currentChildCount = (this.containerElement.childNodes.length + 1) / 2; } else { currentChildCount = this.containerElement.childNodes.length; } if (index == currentChildCount) { index = null; } } if (index == null || !this.containerElement.firstChild) { // Full render, append-at-end scenario, or index 0 specified and no children rendered. // Render spacing cell first if index != 0 and cell spacing enabled. if (this.cellSpacing && this.containerElement.firstChild) { this.containerElement.appendChild(this.spacingPrototype.cloneNode(false)); } // Render child cell second. this.containerElement.appendChild(cellElement); } else { // Partial render insert at arbitrary location scenario (but not at end) var insertionIndex = this.cellSpacing ? index * 2 : index; var beforeElement = this.containerElement.childNodes[insertionIndex]; // Render child cell first. this.containerElement.insertBefore(cellElement, beforeElement); // Then render spacing cell if required. if (this.cellSpacing) { this.containerElement.insertBefore(this.spacingPrototype.cloneNode(false), beforeElement); } } }, /** * Renders all children. Must be invoked by derived <code>renderAdd()</code> implementations. * * @param {Echo.Update.ComponentUpdate} the update */ renderAddChildren: function(update) { this._childIdToElementMap = {}; var componentCount = this.component.getComponentCount(); for (var i = 0; i < componentCount; ++i) { var child = this.component.getComponent(i); this._renderAddChild(update, child); } Core.Web.Event.add(this.element, Core.Web.Env.QUIRK_IE_KEY_DOWN_EVENT_REPEAT ? "keydown" : "keypress", Core.method(this, this.processKeyPress), false); }, /** @see Echo.Render.ComponentSync#renderDispose */ renderDispose: function(update) { Core.Web.Event.removeAll(this.element); this.element = null; this.containerElement = null; this._childIdToElementMap = null; this.spacingPrototype = null; }, /** * Removes a child cell. * * @param {Echo.Update.ComponentUpdate} the update * @param {Echo.Component} the child to remove */ _renderRemoveChild: function(update, child) { var childElement = this._childIdToElementMap[child.renderId]; if (!childElement) { return; } if (this.cellSpacing) { // If cell spacing is enabled, remove a spacing element, either before or after the removed child. // In the case of a single child existing in the Row, no spacing element will be removed. if (childElement.previousSibling) { this.containerElement.removeChild(childElement.previousSibling); } else if (childElement.nextSibling) { this.containerElement.removeChild(childElement.nextSibling); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -