📄 sync.accordionpane.js
字号:
/**
* Component rendering peer: AccordionPane
*/
Extras.Sync.AccordionPane = Core.extend(Echo.Render.ComponentSync, {
$static: {
_defaultTabBackground: "#cfcfcf",
_defaultTabBorder: "1px outset #cfcfcf",
_defaultTabForeground: "#000000",
_defaultTabInsets: "2px 5px",
_defaultTabContentInsets: 0
},
$load: function() {
Echo.Render.registerPeer("Extras.AccordionPane", this);
},
_animationTime: 0,
_div: null,
_activeTabId: null,
_rotation: null,
_animationEnabled: true,
_tabs: null,
_resetOverflowForAnimation: false,
$construct: function() {
this._tabs = [];
this._resetOverflowForAnimation = Core.Web.Env.BROWSER_MOZILLA || Core.Web.Env.BROWSER_INTERNET_EXPLORER;
},
renderAdd: function(update, parentElement) {
this._animationTime = this.component.render("animationTime", Extras.AccordionPane.DEFAULT_ANIMATION_TIME);
this._activeTabId = this.component.get("activeTab");
this._div = document.createElement("div");
this._div.id = this.component.renderId;
this._div.style.cssText = "position:absolute;width:100%;height:100%;";
Echo.Sync.renderComponentDefaults(this.component, this._div);
var componentCount = this.component.getComponentCount();
for (var i = 0; i < componentCount; ++i) {
var child = this.component.getComponent(i);
var tab = new Extras.Sync.AccordionPane.Tab(child, this);
this._tabs.push(tab);
tab._render(this.client, update);
this._div.appendChild(tab._tabDiv);
this._div.appendChild(tab._containerDiv);
}
parentElement.appendChild(this._div);
},
renderDisplay: function() {
if (!this._rotation) {
this._redrawTabs(false);
}
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._div;
var containerElement = element.parentNode;
Echo.Render.renderComponentDispose(update, update.parent);
containerElement.removeChild(element);
this.renderAdd(update, containerElement);
}
return fullRender;
},
renderDispose: function(update) {
if (this._rotation) {
this._rotation.abort();
}
this._activeTabId = null;
for (var i = 0; i < this._tabs.length; i++) {
this._tabs[i]._dispose();
}
this._tabs = [];
this._div = null;
},
/**
* 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(true);
}
},
/**
* 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._tabDiv.parentNode.removeChild(tab._tabDiv);
tab._containerDiv.parentNode.removeChild(tab._containerDiv);
tab._dispose();
},
/**
* Redraws tabs in the appropriate positions, exposing the content of the
* selected tab.
*/
_redrawTabs: function(notifyComponentUpdate) {
if (this._rotation) {
this._rotation.abort();
}
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;
for (var i = 0; i < this._tabs.length; ++i) {
if (selectionPassed) {
this._tabs[i]._tabDiv.style.top = "";
this._tabs[i]._tabDiv.style.bottom = this.getTabHeight(i + 1, this._tabs.length ) + "px";
} else {
this._tabs[i]._tabDiv.style.bottom = "";
this._tabs[i]._tabDiv.style.top = this.getTabHeight(0, i) + "px";
}
this._tabs[i]._containerDiv.style.height = "";
if (this._activeTabId == this._tabs[i]._childComponent.renderId) {
selectionPassed = true;
this._tabs[i]._containerDiv.style.display = "block";
this._tabs[i]._containerDiv.style.top = this.getTabHeight(0, i + 1) + "px";
this._tabs[i]._containerDiv.style.bottom = this.getTabHeight(i + 1, this._tabs.length) + "px";
this._tabs[i]._contentDiv.style.top = 0;
this._tabs[i]._contentDiv.style.bottom = 0;
this._tabs[i]._contentDiv.style.height = "";
Core.Web.VirtualPosition.redraw(this._tabs[i]._contentDiv);
} else {
this._tabs[i]._containerDiv.style.display = "none";
}
}
if (notifyComponentUpdate) {
Echo.Render.renderComponentDisplay(this.component);
}
},
/**
* "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(true);
return;
}
var oldTab = this._getTabById(oldTabId);
if (oldTab == null) {
// Old tab has been removed.
this._redrawTabs(true);
return;
}
if (this._rotation) {
// Rotation was already in progress, cancel
this._rotation.abort();
this._redrawTabs(true);
} else {
// Start new rotation.
var newTab = this._getTabById(newTabId);
this._rotation = new Extras.Sync.AccordionPane.Rotation(this, oldTab, newTab);
this._rotation.runTime = this._animationTime;
this._rotation.start();
}
},
/**
* 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 : Extras.Sync.AccordionPane._defaultTabBackground;
},
_getTabBorder: function() {
var border = this.component.render("tabBorder");
return border ? border : Extras.Sync.AccordionPane._defaultTabBorder;
},
/**
* Determines the height of one or more tabs.
*
* If only beginIndex is specified, the height of the tab at index beginIndex will be returned.
* Note that if endIndex is specified, the tab at index endIndex will NOT be included in the calculation,
* that is, to measure the height of tabs 2, 3, and 4, it is necessary specify beginIndex as 2 and endIndex as 5 (not 4).
*
* @param beginIndex the begin index, inclusive
* @param endIndex the end index, exclusive
*/
getTabHeight: function(beginIndex, endIndex) {
if (endIndex == null || endIndex < beginIndex) {
throw new Error("Invalid indices: begin=" + beginIndex + ",end=" + endIndex);
} else {
var tabHeight = 0;
for (var i = beginIndex; i < endIndex; ++i) {
tabHeight += this._tabs[i]._tabDiv.offsetHeight;
}
return tabHeight;
}
},
_getTabInsets: function() {
var insets = this.component.render("tabInsets");
return insets ? insets : Extras.Sync.AccordionPane._defaultTabInsets;
}
});
Extras.Sync.AccordionPane.Tab = Core.extend({
_rendered: false,
_tabDiv: null,
_parent: null,
_containerDiv: null,
_childComponent: null,
$construct: function(childComponent, parent) {
this._childComponent = childComponent;
this._parent = parent;
},
_dispose: function() {
Core.Web.Event.removeAll(this._tabDiv);
this._parent = null;
this._childComponent = null;
this._tabDiv = null;
this._containerDiv = null;
},
_highlight: function(state) {
var tabDiv = this._tabDiv,
border,
borderData,
borderDataBottom;
if (state) {
var background = this._parent.component.render("tabRolloverBackground");
if (!background) {
background = Echo.Sync.Color.adjust(this._parent._getTabBackground(), 20, 20, 20);
}
Echo.Sync.Color.render(background, tabDiv, "backgroundColor");
var backgroundImage = this._parent.component.render("tabRolloverBackgroundImage");
if (backgroundImage) {
tabDiv.style.backgroundImage = "";
tabDiv.style.backgroundPosition = "";
tabDiv.style.backgroundRepeat = "";
Echo.Sync.FillImage.render(backgroundImage, tabDiv, null);
}
var foreground = this._parent.component.render("tabRolloverForeground");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -