📄 render.accordionpane.js
字号:
// FIXME Update animation to use WebCore.Scheduler.
// FIXME handle enabled/disabled state
/**
* Component rendering peer: AccordionPane
*/
ExtrasRender.ComponentSync.AccordionPane = Core.extend(EchoRender.ComponentSync, {
$static: {
_paneInsets: 0,
_defaultTabBackground: "#cfcfcf",
_defaultTabBorder: "1px outset #cfcfcf",
_defaultTabForeground: "#000000",
_defaultTabHeight: "20px",
_defaultTabInsets: "2px 5px",
_defaultTabContentInsets: this._paneInsets
},
$load: function() {
EchoRender.registerPeer("ExtrasApp.AccordionPane", this);
},
_animationTime: 0,
$construct: function() {
this._paneDivElement = null;
this._activeTabId = null;
this._tabs = [];
this._rotation = null;
this._animationEnabled = true;
this._animationSleepInterval = 1;
},
renderAdd: function(update, parentElement) {
this._animationTime = this.component.render("animationTime", ExtrasApp.AccordionPane.DEFAULT_ANIMATION_TIME);
this._activeTabId = this.component.get("activeTab");
this._paneDivElement = this._render();
var componentCount = this.component.getComponentCount();
for (var i = 0; i < componentCount; ++i) {
var child = this.component.getComponent(i);
var tab = new ExtrasRender.ComponentSync.AccordionPane.Tab(child, this);
this._tabs.push(tab);
tab._render(this.client, update);
this._paneDivElement.appendChild(tab._tabDivElement);
this._paneDivElement.appendChild(tab._contentDivElement);
}
this._redrawTabs();
parentElement.appendChild(this._paneDivElement);
},
renderDisplay: function() {
for (var i = 0; i < this._tabs.length; ++i) {
this._tabs[i]._renderDisplay();
}
},
renderUpdate: function(update) {
var fullRender;
if (update.hasUpdatedLayoutDataChildren() || update.hasAddedChildren() || update.hasRemovedChildren()) {
// Add/remove/layout data change: full render.
fullRender = true;
} else {
var propertyNames = update.getUpdatedPropertyNames();
if (propertyNames.length == 1 && propertyNames[0] == "activeTab") {
this._selectTab(update.getUpdatedProperty("activeTab").newValue);
fullRender = false;
} else {
fullRender = true;
}
}
if (fullRender) {
var element = this._paneDivElement;
var containerElement = element.parentNode;
EchoRender.renderComponentDispose(update, update.parent);
containerElement.removeChild(element);
this.renderAdd(update, containerElement);
}
return fullRender;
},
renderDispose: function(update) {
if (this._rotation) {
this._rotation._dispose();
}
this._activeTabId = null;
for (var i = 0; i < this._tabs.length; i++) {
this._tabs[i]._dispose();
}
this._tabs = [];
this._paneDivElement.id = "";
this._paneDivElement = null;
},
_render: function() {
var paneDivElement = document.createElement("div");
paneDivElement.id = this.component.renderId;
paneDivElement.style.position = "absolute";
paneDivElement.style.overflow = "hidden";
paneDivElement.style.width = "100%";
paneDivElement.style.height = "100%";
EchoAppRender.Color.renderFB(this.component, paneDivElement);
EchoAppRender.Font.render(this.component.render("font"), paneDivElement);
return paneDivElement;
},
/**
* Selects a specific tab.
*
* @param tabId {String} the id of the tab to select
*/
_selectTab: function(tabId) {
if (tabId == this._activeTabId) {
return;
}
this.component.set("activeTab", tabId);
var oldTabId = this._activeTabId;
this._activeTabId = tabId;
if (oldTabId != null && this._animationEnabled) {
this._rotateTabs(oldTabId, tabId);
} else {
this._redrawTabs();
}
},
/**
* Removes a tab from an AccordionPane.
*
* @param tab the tab to remove
*/
_removeTab: function(tab) {
var tabIndex = Core.Arrays.indexOf(this._tabs, tab);
this._tabs.splice(tabIndex, 1);
tab._tabDivElement.parentNode.removeChild(tab._tabDivElement);
tab._contentDivElement.parentNode.removeChild(tab._contentDivElement);
tab._dispose();
},
/**
* Redraws tabs in the appropriate positions, exposing the content of the
* selected tab.
*/
_redrawTabs: function() {
if (this._rotation) {
this._rotation._cancel();
}
if (this._activeTabId == null || this._getTabById(this._activeTabId) == null) {
if (this._tabs.length > 0) {
this._activeTabId = this._tabs[0]._childComponent.renderId;
} else {
this._activeTabId = null;
}
}
var selectionPassed = false;
var tabHeight = this._calculateTabHeight();
for (var i = 0; i < this._tabs.length; ++i) {
var tab = this._tabs[i];
var tabDivElement = tab._tabDivElement;
var contentDivElement = tab._contentDivElement;
if (selectionPassed) {
tabDivElement.style.top = "";
tabDivElement.style.bottom = (tabHeight * (this._tabs.length - i - 1)) + "px";
} else {
tabDivElement.style.bottom = "";
tabDivElement.style.top = (tabHeight * i) + "px";
}
contentDivElement.style.height = "";
if (this._activeTabId == tab._childComponent.renderId) {
selectionPassed = true;
contentDivElement.style.display = "block";
contentDivElement.style.top = (tabHeight * (i + 1)) + "px";
var bottomPx = tabHeight * (this._tabs.length - i - 1);
contentDivElement.style.bottom = bottomPx + "px";
} else {
contentDivElement.style.display = "none";
}
}
},
/**
* "Rotates" the AccordionPane to display the specified tab.
*
* @param oldTabId {String} the currently displayed tab id
* @param newTabId {String} the id of the tab that will be displayed
*/
_rotateTabs: function(oldTabId, newTabId) {
if (this._animationTime < 1) {
this._redrawTabs();
return;
}
var oldTab = this._getTabById(oldTabId);
if (oldTab == null) {
// Old tab has been removed.
this._redrawTabs();
return;
}
if (this._rotation) {
// Rotation was already in progress, cancel
this._rotation._cancel();
this._redrawTabs();
} else {
// Start new rotation.
var newTab = this._getTabById(newTabId);
this._rotation = new ExtrasRender.ComponentSync.AccordionPane.Rotation(this, oldTab, newTab);
}
},
/**
* Retrieves the tab instance with the specified tab id.
*
* @param tabId the tab id
* @return the tab, or null if no tab is present with the specified id
*/
_getTabById: function(tabId) {
for (var i = 0; i < this._tabs.length; ++i) {
var tab = this._tabs[i];
if (tab._childComponent.renderId == tabId) {
return tab;
}
}
return null;
},
_getTabBackground: function() {
var background = this.component.render("tabBackground");
return background ? background : ExtrasRender.ComponentSync.AccordionPane._defaultTabBackground;
},
_getTabBorder: function() {
var border = this.component.render("tabBorder");
return border ? border : ExtrasRender.ComponentSync.AccordionPane._defaultTabBorder;
},
_getTabInsets: function() {
var insets = this.component.render("tabInsets");
return insets ? insets : ExtrasRender.ComponentSync.AccordionPane._defaultTabInsets;
},
/**
* @return the tab height in pixels
* @type {Number}
*/
_calculateTabHeight: function() {
var height = EchoAppRender.Extent.toPixels(ExtrasRender.ComponentSync.AccordionPane._defaultTabHeight);
var insets = EchoAppRender.Insets.toPixels(this._getTabInsets());
var border = this._getTabBorder();
return height + insets.top + insets.bottom + EchoAppRender.Border.getPixelSize(border) * 2;
}
});
ExtrasRender.ComponentSync.AccordionPane.Tab = Core.extend({
$construct: function(childComponent, parent) {
this._childComponent = childComponent;
this._parent = parent;
this._rendered = false;
this._tabDivElement = null;
this._contentDivElement = null;
},
_render: function(client, update) {
this._tabDivElement = document.createElement("div");
this._tabDivElement.id = this._parent.component.renderId + "_tab_" + this._childComponent.renderId;
this._tabDivElement.style.cursor = "pointer";
this._tabDivElement.style.height = ExtrasRender.ComponentSync.AccordionPane._defaultTabHeight;
EchoAppRender.Insets.render(this._parent._getTabInsets(), this._tabDivElement, "padding");
this._tabDivElement.style.position = "absolute";
this._tabDivElement.style.left = "0px";
this._tabDivElement.style.right = "0px";
this._tabDivElement.style.overflow = "hidden";
this._tabDivElement.appendChild(document.createTextNode(this._getTitle()));
this._contentDivElement = document.createElement("div");
this._contentDivElement.id = this._parent.component.renderId + "_content_" + this._childComponent.renderId;
this._contentDivElement.style.display = "none";
this._contentDivElement.style.position = "absolute";
this._contentDivElement.style.left = "0px";
this._contentDivElement.style.right = "0px";
EchoAppRender.Insets.render(this._getContentInsets(), this._contentDivElement, "padding");
this._contentDivElement.style.overflow = "auto";
EchoRender.renderComponentAdd(update, this._childComponent, this._contentDivElement);
this._highlight(false);
this._addEventListeners();
},
_renderDisplay: function() {
WebCore.VirtualPosition.redraw(this._tabDivElement);
WebCore.VirtualPosition.redraw(this._contentDivElement);
},
_dispose: function() {
WebCore.EventProcessor.removeAll(this._tabDivElement);
this._parent = null;
this._childComponent = null;
this._tabDivElement.id = "";
this._tabDivElement = null;
this._contentDivElement.id = "";
this._contentDivElement = null;
},
_highlight: function(state) {
var tabDivElement = this._tabDivElement;
if (state) {
var background = this._parent.component.render("tabRolloverBackground");
if (!background) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -