Module:TabberUtils
Jump to navigation
Jump to search
Documentation for this module may be created at Module:TabberUtils/doc
-- Adapted from ZeldaWiki: https://zeldawiki.wiki/w/index.php?title=Module:UtilsLayout/Tabs
-- Edited by Vish
local p = {}
local h = {}
-- Function to parse arguments
function p.parse(frameArgs)
local args = {
tabs = {},
align = "left",
default = 1,
columns = nil,
position = "top",
distribution = nil,
tabAlign = "center",
contentAlign = "left",
}
-- Parse named parameters
for k, v in pairs(frameArgs) do
if k == "align" then
args.align = v
elseif k == "default" then
args.default = tonumber(v) or 1
elseif k == "columns" then
args.columns = tonumber(v)
elseif k == "position" then
args.position = v
elseif k == "distribution" then
args.distribution = v
elseif k == "tabAlign" then
args.tabAlign = v
elseif k == "contentAlign" then
args.contentAlign = v
end
end
-- Parse tab names and contents
local i = 1
while frameArgs[i] or frameArgs["Tab" .. i] do
local key = frameArgs[i] or frameArgs["Tab" .. i]
local value = frameArgs[i + 1] or frameArgs["Content" .. i]
if key and key ~= "" then
table.insert(args.tabs, {
tab = key,
content = value
})
end
i = i + (frameArgs[i] and 2 or 1)
end
return args
end
function p.tabs(data, options)
local options = options or {}
local tabOptions = options.tabOptions or {}
local labelOptions = options.labelOptions or {}
local contentOptions = options.contentOptions or {}
local defaultTab = options.default or 1
local align = options.align or "left"
local tabAlign = options.tabAlign or "center"
local contentAlign = options.contentAlign or "left"
if #data == 1 and tabOptions.collapse then
return data[1].content
end
local tabContainer = h.tabContainer(data, defaultTab, tabAlign, tabOptions, labelOptions)
local tabContents = h.tabContents(data, defaultTab, contentAlign, contentOptions)
local html = mw.html.create("div")
:addClass("jw-tabs")
:addClass(tabOptions.stretch and "jw-tabs--stretch" or nil)
:addClass(tabOptions.columns and "jw-tabs--columns" or nil)
if tabOptions.position == "bottom" then
html:node(tabContents)
:node(tabContainer)
else
html:node(tabContainer)
:node(tabContents)
end
return tostring(html)
end
function h.tabContainer(data, defaultTab, align, tabOptions, labelOptions)
local position = tabOptions.position or "top"
local stretch = tabOptions.stretch
local columns = tabOptions.columns
local labelAlignVertical = labelOptions.alignVertical or "center"
local tabContainer = mw.html.create("div")
:addClass("tabcontainer tabcontainer-"..position)
:addClass("tabcontainer--align-x-"..align)
:attr("role", "tablist")
for i, tabData in ipairs(data) do
local label = tabData.label
local sanitizedLabel = mw.uri.anchorEncode(label)
local tab = mw.html.create("span")
:addClass("tab")
:addClass("tab--label-align-y-"..labelAlignVertical)
:attr("role", "tab")
:attr("tabindex", "0")
:attr("data-tab-hash", sanitizedLabel)
:wikitext(label)
if i == defaultTab then
tab:addClass("active")
end
if columns then
tab:css({
["max-width"] = "calc(100%/"..columns.." - 2*"..(columns-1).."px)" -- the subtraction is to account for tab margins
})
end
tabContainer:node(tab)
end
return tabContainer
end
function h.tabContents(data, defaultTab, align, contentOptions)
local alignVertical = contentOptions.alignVertical or "top"
local fixedWidth = contentOptions.fixedWidth
local fixedHeight = contentOptions.fixedHeight
local tabContents = mw.html.create("div")
:addClass("tabcontents")
:addClass("tabcontents--align-x-"..align)
:addClass("tabcontents--align-y-"..alignVertical)
if fixedWidth then
tabContents:addClass("tabcontents--fixed-width")
if type(fixedWidth) == "number" then
tabContents:css("width", fixedWidth .. "px")
end
end
if fixedHeight then
tabContents:addClass("tabcontents--fixed-height")
if type(fixedHeight) == "number" then
tabContents:css("height", fixedHeight .. "px")
end
end
for i, tabData in ipairs(data) do
local content = mw.html.create("div")
:addClass("content")
:attr("role", "tabpanel")
:wikitext("\n", tabData.content or "")
if i == defaultTab then
content:addClass("content--active")
end
tabContents:node(content)
end
return tabContents
end
return p