Module:Tabs

From BlazBlue Wiki
Revision as of 21:20, 29 November 2019 by Chao (talk | contribs) (initial)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation for this module can be edited at Module:Tabs/doc.

{{#invoke:Tabs|main
|name=
|containerclass=
   forceland (force the tabs to be laid out horizontally above the content)
   forceport (force the tabs to be laid out vertically to the left of the content)
|containerstyle=
|tabstyle=

|tab1=
|tabclass1=
|tabstyle1=

|content1=
|contentclass1=
|contentstyle1=
}}

Tabs can be nested (see BBCP and BBCF tabs below).


--------------------------------------------------------------------------------
--Tab class
--------------------------------------------------------------------------------

local Tab = {}
Tab.__index = Tab

Tab.fields = {
  number = true,
  tabclass = true,
  tabstyle = true,
  contentclass = true,
  contentstyle = true,
  content = true,
  tab = true,
}

function Tab.new(data)
  local self = setmetatable({}, Tab)
  for field in pairs(Tab.fields) do
    self[field] = data[field] or ''
  end
  self.number = assert(tonumber(self.number))
  return self
end

function Tab:getTabName()
  return self.tab
end

function Tab:getTabClass()
  return self.tabclass
end

function Tab:getTabStyle()
  return self.tabstyle
end

function Tab:getContentClass()
  return self.contentclass
end

function Tab:getContentStyle()
  return self.contentstyle
end

function Tab:getContent()
  return self.content
end

--------------------------------------------------------------------------------
-- Tabs class
--------------------------------------------------------------------------------

local Tabs = {}
Tabs.__index = Tabs
Tabs.fields = {
  name = true,
  containerclass = true,
  containerstyle = true,
  ulstyle = true,
  tabstyle = true,
  tabclass = true,
  contentclass = true,
  contentstyle = true
}

function Tabs.new(data)
  local self = setmetatable({}, Tabs)

  -- add properties
  for field in pairs(Tabs.fields) do
    self[field] = data[field] or ''
  end

  -- make tab objects
  self.tabs = {}
  for i, tabData in ipairs(data.tabs or {}) do
    table.insert(self.tabs, Tab.new(tabData))
  end

  return self
end

function Tabs:__tostring()

  -- Root of the output
  local root = mw.html.create()

  -- Wrapper
  div = root:tag('div')
  div
    :attr('id',"tabs-" .. self.name)
    :attr('class','tabdiv')
    :addClass(self.containerclass)
    :cssText(self.containerstyle)

  -- Tab List
  local ul = div:tag('ul')
  ul:cssText(self.ulstyle)

  for i, tab in ipairs(self.tabs) do
    local tabID = self.name .. "tab" .. i
    
    -- Create Tab
    li = ul:tag('li')
    li
      :attr('id',self.name .. "tabtag" .. i)
      :addClass(self.tabclass)
      :addClass(tab:getTabClass())
      :cssText(self.tabstyle .. tab:getTabStyle())
      :wikitext('[[#' .. tabID .. '|' .. tab:getTabName() .. ']]')
    
    -- Create Content
    local contentDiv = div:tag('div')
    contentDiv
      :attr('id',tabID)
      :addClass(self.contentclass)
      :addClass(tab:getContentClass())
      :cssText(self.contentstyle .. tab:getContentStyle())
      :wikitext(tab:getContent())
  end

  return root
end

--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------

local p = {}

function p._main(args)
  -- Process numerical args so that we can iterate through them.
  local data, tabs = {}, {}
  for k, v in pairs(args) do
    if type(k) == 'string' then
      local prefix, num = k:match('^(%D.-)(%d+)$')
      if prefix and Tab.fields[prefix] and (num == '0' or num:sub(1, 1) ~= '0') then
        -- Allow numbers like 0, 1, 2 ..., but not 00, 01, 02...,
        -- 000, 001, 002... etc.
        num = tonumber(num)
        tabs[num] = tabs[num] or {}
        tabs[num][prefix] = v
      else
        data[k] = v
      end
    end
  end
  data.tabs = (function (t)
    -- Compress sparse array
    local ret = {}
    for num, tabData in pairs(t) do
      tabData.number = num
      table.insert(ret, tabData) 
    end
    table.sort(ret, function (t1, t2)
      return t1.number < t2.number
    end)
    return ret
  end)(tabs)

  return tostring(Tabs.new(data))
end

function p.main(frame)
  local args = require('Module:Arguments').getArgs(frame)
  return p._main(args)
end

return p