📄 zptabs-accordion.js
字号:
var funcOnBeforeTabChange = self.config.onBeforeTabChange;
self.config.onBeforeTabChange = function(objArgs)
{
// Call original function
if (typeof funcOnBeforeTabChange == 'function')
{
return funcOnBeforeTabChange(objArgs);
}
return true;
};
// Patch onTabChange handler
var funcOnTabChange = self.config.onTabChange;
self.config.onTabChange = function(objArgs)
{
// Get new tab id
var strNewTabId = objArgs.newTabId;
// Get new tab
var objNewTab = self.tabs[strNewTabId];
if (!objNewTab)
{
return;
}
// Call original function
if (typeof funcOnTabChange == 'function')
{
funcOnTabChange(objArgs);
}
};
// Call original function
if (typeof funcOnInit == 'function')
{
funcOnInit(objArgs);
}
};
// Disable tab bar
this.noTabBar = true;
// Define config options
this.config.windowOnLoad = null;
// Tab controllers
this.config._tabArray = new Array();
this.config.IN_MOTION = false;
this.config.tabBarHeight = 24;
this.config.topPos = null;
this.config.indexOfWidget = i;
this.tabsThemeSuffix = 'AccordionContent';
// Call parent init
Zapatec.AccordionTabs.SUPERclass.init.call(this, objArgs);
}
/**
* Adds a new tab.
*
* @private
* Following format is recognized:
* \code
* {
* id: [string, optional] id of the tab,
* innerHTML: [string] label,
* accessKey: [string, optional] access key,
* title: [string] title,
* url: [string] URL of the content,
* tabType: [string] "div" or "iframe" for the content pane
* index: [number, optional] index to make insert the new tab at
* }
* \endcode
*
* @param {object} objTabDef JSON object.
*/
Zapatec.AccordionTabs.prototype.addTab = function(objTabDef) {
if (!objTabDef.collapseOnClick) {
// Use config option from Tabs
objTabDef.collapseOnClick = this.config.collapseOnClick;
}
// Call parent addTab
var objTab = Zapatec.AccordionTabs.SUPERclass.addTab.call(this, objTabDef);
// Store index of tab container within tabs
objTab.tabContainer.index = objTab.index;
return objTab;
}
/**
* Create a new tab instance
*
* @param {object} objArgs tab configuration
*/
Zapatec.AccordionTabs.prototype.newTab = function(objArgs) {
var objTab = new Zapatec.AccordionTab(objArgs);
return objTab;
}
/**
* Display a new accordion tab. If onBeforeTabChange() returns false, the
* operation is cancelled.
*
* @param {string} strNewTabId id of the new tab.
*/
Zapatec.AccordionTabs.prototype.changeTab = function(strNewTabId) {
var strCurrTabId = null;
var objTab = null;
if (this.tabsArray[this.currentIndex])
{
strCurrTabId = this.tabsArray[this.currentIndex].id;
objTab = this.tabsArray[this.currentIndex];
}
if (strCurrTabId != strNewTabId && !this.config.IN_MOTION)
{
// Check if callback function allows to change tab
var boolChangeTab = true;
if (typeof this.config.onBeforeTabChange == 'function') {
boolChangeTab = this.config.onBeforeTabChange({
oldTabId: strCurrTabId,
newTabId: strNewTabId
});
}
if (!boolChangeTab) {
return;
}
// Change tab
if (objTab)
{
Zapatec.Utils.removeClass(objTab.linkNode, 'zpTabsActive');
}
objTab = this.getTab(strNewTabId);
var oOffset = Zapatec.Utils.getElementOffset(this.config.tabs);
// Setup WCH
Zapatec.Utils.setupWCH(objTab.wch, 0, 0, oOffset.width, oOffset.height);
Zapatec.Utils.addClass(objTab.linkNode, 'zpTabsActive');
this.currentIndex = objTab.index;
// Initiate sliding:
this.slide(objTab.tabContainer.arrayPosition, 5, 10);
// Reload tab if needed and call onTabChange
this.refreshTab(objTab, strCurrTabId, strNewTabId);
}
else {
// If collapseOnClick config option is set and
// the current tab is being re-activated
if (this.config.collapseOnClick && strCurrTabId == strNewTabId &&
!this.config.IN_MOTION) {
// Collapse active tab
this.collapseTab();
}
}
};
/**
* Scrolls tabs to the left. Moves tab(s) by pxInc every timeInc
*
* @private
* @param {boolean} setTab Whether the function should set the selected tab
* on its own.
*/
Zapatec.AccordionTabs.prototype.slide = function(index, pxInc, timeInc) {
if (false == this.config.IN_MOTION) {
var date = new Date();
this.moveStartTime = date.getTime();
this.lastTime = this.moveStartTime - timeInc;
this.isDecreaseHeight = true;
}
// Test for index validity
if (isNaN(index) || index < -1 || index >= this.config._tabArray.length)
{
// Allow switching again
this.config.IN_MOTION = false;
return;
}
var date = new Date();
var time = date.getTime();
// Calculate time elapsed since last frame
var diffTime = time - this.lastTime;
// Calculate pixels difference for elapsed time
var inc = Math.round((diffTime / timeInc) * pxInc);
if (0 == inc) {
var self = this;
// Go again
setTimeout(function() {
self.slide(index, pxInc, timeInc);
}, timeInc);
return;
}
this.lastTime = time;
var resizeTabs = {decreaseDif: 0, increaseDif: 0};
// Flags if any tab has been resized
var isAdjust = false;
// Find 1 tab to increase and 1 tab to decrease
for (var tries = 0; tries < 2; tries++) {
for (var i = 0; i < this.config._tabArray.length; i++)
{
var tab = this.getTabByIndex(i);
var tabContainer = tab.tabContainer;
var contentContainer = tab.container.getContainer();
var newHeight = -1;
var oldHeight = parseInt(contentContainer.style.height);
var isCurrent = tab.index == this.currentIndex;
if (!isCurrent && this.isDecreaseHeight) {
newHeight = oldHeight - inc;
// Check for lower limit
if (newHeight < 1) {
newHeight = 1;
}
}
else if (isCurrent && !this.isDecreaseHeight) {
newHeight = oldHeight + inc;
// Watch out for upper limit
if (tabContainer.viewingHeight <= newHeight) {
newHeight = tabContainer.viewingHeight;
}
}
// If a new height is determined
if (-1 != newHeight && oldHeight != newHeight) {
if (this.isDecreaseHeight) {
resizeTabs.decreaseTab = contentContainer;
resizeTabs.decreaseDif = oldHeight - newHeight;
}
else {
resizeTabs.increaseTab = contentContainer;
resizeTabs.increaseDif = newHeight - oldHeight;
}
isAdjust = true;
break;
}
}
this.isDecreaseHeight = !this.isDecreaseHeight;
}
var dif;
if (resizeTabs.increaseTab && resizeTabs.decreaseTab) {
dif = Math.min(resizeTabs.decreaseDif, resizeTabs.increaseDif);
}
else if (!resizeTabs.increaseTab) {
dif = resizeTabs.decreaseDif;
}
else {
dif = resizeTabs.increaseDif;
}
var incTab = resizeTabs.increaseTab;
var decTab = resizeTabs.decreaseTab;
if (incTab) {
var incOldHeight = parseInt(incTab.style.height);
incTab.style.height = (incOldHeight + dif) + 'px';
if (this.isLoadedHtml && incTab.tagName &&
incTab.tagName.toLowerCase() != 'iframe') {
var tabContentDiv = Zapatec.Utils.getFirstChild(incTab, "div");
Zapatec.Utils.addClass(tabContentDiv, "zpTabsNoOverflow");
}
Zapatec.Utils.addClass(incTab, "zpTabsNoOverflow");
}
if (decTab) {
var decOldHeight = parseInt(decTab.style.height);
if (!incTab && this.config.scrollPageOnSlide) {
var scrollY = Zapatec.Utils.getPageScrollY();
var winSize = Zapatec.Utils.getWindowSize();
var decTabPos = Zapatec.Utils.getAbsolutePos(decTab);
var scrollPosBottom = scrollY + winSize.height - document.body.clientHeight;
// If vertical scroller is at the bottom
if (0 <= scrollPosBottom && scrollPosBottom < 20) {
var y = decTabPos.y + decOldHeight - winSize.height;
if (y < 0) {
y = 0;
}
window.scrollTo(0, y);
}
// If decreased tab goes up from browser viewport
if (decTabPos.y + decOldHeight - dif < scrollY) {
var y = decTabPos.y + decOldHeight - winSize.height;
if (y < 0) {
y = 0;
}
window.scrollTo(0, y);
}
}
decTab.style.height = (decOldHeight - dif) + 'px';
if (this.isLoadedHtml && decTab.tagName &&
decTab.tagName.toLowerCase() != 'iframe') {
var tabContentDiv = Zapatec.Utils.getFirstChild(decTab, "div");
Zapatec.Utils.addClass(tabContentDiv, "zpTabsNoOverflow");
}
Zapatec.Utils.addClass(decTab, "zpTabsNoOverflow");
}
if (!isAdjust) {
// Allow switching again
this.config.IN_MOTION = false;
if (-1 != this.currentIndex) {
var currentTab = this.getTabByIndex(this.currentIndex);
var stoppedTabContainer = currentTab.container.getContainer();
Zapatec.Utils.removeClass(stoppedTabContainer, "zpTabsNoOverflow");
}
return;
}
// Stop switching while this process is running
this.config.IN_MOTION = true;
var self = this;
// Go again
setTimeout(function() {
self.slide(index, pxInc, timeInc);
}, timeInc);
}
/**
* Collapses the currently active tab
*
* @private
*/
Zapatec.AccordionTabs.prototype.collapseTab = function() {
if (-1 != this.currentIndex) {
var currentTab = this.getTabByIndex(this.currentIndex);
Zapatec.Utils.removeClass(currentTab.linkNode, 'zpTabsActive');
}
this.currentIndex = -1;
// Initiate sliding:
this.slide(-1, 5, 10);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -