Module:InfoboxBuilder: Difference between revisions

From Sekaipedia
Content added Content deleted
(changed to options table, applies to headers, images, and rows)
m (version bump)
 
(38 intermediate revisions by the same user not shown)
Line 1: Line 1:
-----------------------------------------------------------------------
-- InfoboxBuilder v1.1.1 --
-----------------------------------------------------------------------
-- Builds an infobox using Lua
--
-- Dependencies:
-- * Extensions
-- ** TemplateStyles
-- ** Tabber/TabberNeue
-- * Modules
-- ** Navbar
-- * Styles
-- ** Module:InfoboxBuilder/styles.css

local Navbar = require('Module:Navbar')._navbar

local InfoboxBuilder = {}
local InfoboxBuilder = {}
InfoboxBuilder.__index = InfoboxBuilder
InfoboxBuilder.__index = InfoboxBuilder
Line 17: Line 33:
name = '',
name = '',
headerColors = {
headerColors = {
text = '#000',
['color'] = nil,
['background-color'] = nil
bg = 'transparent'
},
params = {
['bg color'] = {},
['text color'] = {}
},
},
params = {},
param_names = { 'bg color', 'text color' },
paramNames = { 'bg color', 'text color' },
raw_args = {},
proc_args = {},
rawArgs = {},
procArgs = {},
infobox = mw.html.create('table'):addClass('infobox'),
categoryMap = {},
infobox = mw.html.create('table')
:addClass('infobox')
:css('width', '330px'),
finished = false
finished = false
}, InfoboxBuilder)
}, InfoboxBuilder)
Line 41: Line 57:
function InfoboxBuilder:setName(arg)
function InfoboxBuilder:setName(arg)
if arg == nil or arg == '' then
if arg == nil or arg == '' then
error("Template name must not be nil or empty")
error('Template name must not be nil or empty')
end
end
self.name = arg
self.name = arg
return self
end

--- Set the width of the infobox
-- @param arg string
-- Width of the infobox, should be a valid value for the CSS "width"
-- property, not nil or empty
-- @return self
-- The current object
function InfoboxBuilder:setWidth(arg)
if arg == nil or arg == '' then
error("Width must not be nil or empty")
end
self.infobox:css('width', arg)
return self
return self
Line 73: Line 73:
function InfoboxBuilder:setHeaderTextColor(arg)
function InfoboxBuilder:setHeaderTextColor(arg)
if arg == nil or arg == '' then
if arg == nil or arg == '' then
error("Header text color must not be nil or empty")
error('Header text color must not be nil or empty')
end
end
self.headerColors.text = arg
self.headerColors['color'] = arg
return self
return self
Line 89: Line 89:
function InfoboxBuilder:setHeaderBackgroundColor(arg)
function InfoboxBuilder:setHeaderBackgroundColor(arg)
if arg == nil or arg == '' then
if arg == nil or arg == '' then
error("Header background color must not be nil or empty")
error('Header background color must not be nil or empty')
end
end
self.headerColors.bg = arg
self.headerColors['background-color'] = arg
return self
end

--- Sets both the text and background color of the header
-- @param arg { text, bg }
-- text string
-- Same as setHeaderTextColor
-- bg string
-- Same as setHeaderBackgroundColor
-- @return self
-- The current object
function InfoboxBuilder:setHeaderColors(arg)
if arg == nil then
error("Header colors must not be nil")
end
self:setHeaderTextColor(arg.text)
self:setHeaderBackgroundColor(arg.bg)
return self
end

--- Sets both the text and background color of the header
-- @param param_name string
-- Parameter name that helps map the colors
-- @param color_table { text, bg }
-- text string
-- Same as setHeaderTextColor
-- bg string
-- Same as setHeaderBackgroundColor
-- @return self
-- The current object
function InfoboxBuilder:setHeaderColorsByParam(param_name, color_table)
if param_name == nil then
error("Parameter name must not be nil")
elseif color_table == nil then
error("Header color table must not be nil")
end
local raw_param_value = self.raw_args[param_name]
local colors = color_table[raw_param_value]
if colors == nil then
return self
end
self:setHeaderTextColor(colors.text)
self:setHeaderBackgroundColor(colors.bg)
return self
return self
Line 147: Line 98:


--- Sets the infobox params
--- Sets the infobox params
-- @param ... {{ name, func, default, should_hide }, ...}
-- @param ... {{ name, fn, default }, ...}
-- name string
-- name string
-- The name of the parameter, not nil, cannot be duplicate
-- The name of the parameter, not nil, cannot be duplicate
-- func function, table or string
-- fn A function or table that processes the raw arguments
-- A function that accepts the parameter as an argument and
-- - A function that accepts the parameter as an argument and
-- returns a string, OR
-- returns a string or list, OR
-- A table that has the parameter as a key, OR
-- - A table that has the parameter as a key
-- An empty string
-- default string or nil
-- default string or nil
-- The default value if no argument is given
-- The default value if no argument is given
Line 160: Line 110:
-- The current object
-- The current object
function InfoboxBuilder:setParams(...)
function InfoboxBuilder:setParams(...)
for i, v in ipairs(...) do
for _, p in ipairs(...) do
if v.name == nil and v.name == "" then
if p.name == nil or p.name == '' then
error("name must not be nil or empty")
error('Param name must not be nil or empty')
end
end
if self.param_names[v.name] then
if self.paramNames[p.name] then
error("name cannot be duplicate")
error('Param name cannot be duplicate')
end
end
self.params[v.name] = {
self.params[p.name] = {
['type'] = type(v.func),
fn = p.fn,
func = v.func,
default = p.default
default = v.default
}
}
table.insert(self.param_names, v.name)
table.insert(self.paramNames, p.name)
end
end
Line 185: Line 134:
-- The current object
-- The current object
function InfoboxBuilder:setArgs(args)
function InfoboxBuilder:setArgs(args)
for k,v in pairs(args) do
for name, value in pairs(args) do
if v ~= '' then
if value ~= '' then
self.raw_args[k] = v
self.rawArgs[name] = value
end
end
end
end
if self.raw_args['bg color'] then
if self.rawArgs['bg color'] then
self:setHeaderBackgroundColor(self.raw_args['bg color'])
self:setHeaderBackgroundColor(self.rawArgs['bg color'])
end
end
if self.raw_args['text color'] then
if self.rawArgs['text color'] then
self:setHeaderTextColor(self.raw_args['text color'])
self:setHeaderTextColor(self.rawArgs['text color'])
end
end
Line 201: Line 150:
end
end


--- Gets the content associated with a parameter
--- Gets the raw argument values passed
-- @param param_name string
-- @return args table
-- The param name, not nil or empty
-- A table containing the args
function InfoboxBuilder:getRawArgs()
-- @return content string
return self.rawArgs
-- A string containing the content
end
function InfoboxBuilder:getContent(param_name)

if param_name == nil or param_name == "" then
--- Gets the argument values after being processed
error("Param must not be nil or empty")
-- @return args table
-- A table containing the args
function InfoboxBuilder:getProcessedArgs()
return self.procArgs
end

--- Gets the argument values of the table, for either raw or processed
-- @param which string
-- A string that determines which argument values to return
-- @retun args table
-- A table containing the args
function InfoboxBuilder:getArgs(which)
if which == 'raw' then
return self:getRawArgs()
elseif which == 'processed' then
return self:getProcessedArgs()
end
end
return {}
if self.proc_args[param_name] then
end
return self.proc_args[param_name]

--- Sets the category map for each param
-- @param catMap
-- @return self
-- The current object
function InfoboxBuilder:setCategoryMap(catMap)
if catMap and type(catMap) == 'table' then
self.categoryMap = catMap
end
end
return self
local content = nil
end
local current_param = self.params[param_name]

--- Returns categories based on processed args
if current_param == nil then
-- @return categories string
error(string.format("No such param with name: %s", param_name))
-- A string containing with all the categories
function InfoboxBuilder:getCategories()
local categories = {}
for name, value in pairs(self.procArgs) do
local catMap = self.categoryMap[name]
local valueType = type(value)
if catMap then
if valueType == 'string' or
valueType == 'boolean' or
valueType == 'number' then
if catMap[value] then
table.insert(
categories,
string.format('[[Category:%s]]', catMap[value])
)
end
elseif valueType == 'table' then
for _, val in ipairs(value) do
if catMap[val] then
table.insert(
categories,
string.format('[[Category:%s]]', catMap[val])
)
end
end
end
end
end
end
return table.concat(categories, '')
local raw_param_value = self.raw_args[param_name] or current_param.default
end

if raw_param_value == nil then
--- Processes raw args into a format usable by auto categorizer and display functions
return raw_param_value
-- @return self
-- The current object
function InfoboxBuilder:processArgs()
for name, param in pairs(self.params) do
local value = self.rawArgs[name] or param.default
local fn = param.fn
local fnType = type(fn)
if value then
if fnType == 'function' then
value = fn(value)
elseif fnType == 'table' then
value = fn[value]
end
end
self.procArgs[name] = value
end
end
return self
if current_param['type'] == 'function' then
end
content = current_param.func(raw_param_value)

elseif current_param['type'] == 'table' then
--- Gets the content associated with a parameter or parameters
content = current_param.func[raw_param_value]
-- @param paramNames string or {...}
-- The param name(s), not nil or empty
-- @param fn function
-- A function that turns an array of processed args into a
-- string. The order of parameters is identical to paramNames.
-- Used to transform args into their final display format.
-- @return string content
-- A string containing the content
function InfoboxBuilder:getContent(paramNames, fn)
if paramNames == nil then
error('Params must not be nil')
else
else
if type(paramNames) == 'table' then
content = raw_param_value
if #paramNames == 0 then
error('There must be more than one param used')
end
elseif type(paramNames) == 'string' then
paramNames = { paramNames }
end
end
end
local contents = {}
for i, paramName in ipairs(paramNames) do
self.proc_args[param_name] = content
if paramName == '' then
error('Param name must not be empty')
elseif self.params[paramName] == nil then
error(string.format('No such param with name: %s', paramName))
end
-- Must assign by index to preserve nil
contents[i] = self.procArgs[paramName]
end
local content = nil
if type(fn) == 'function' then
content = fn(unpack(contents))
elseif #paramNames == 1 then
content = contents[1]
end
return content
return content
Line 242: Line 296:


--- Determines if the row should be shown based of a list of param names
--- Determines if the row should be shown based of a list of param names
-- @param param_names { param_name, ... }
-- @param paramNames { paramName, ... }
-- param_name string
-- paramName string
-- The param name
-- The param name
-- @return should_show boolean
-- @return shouldShow boolean
function InfoboxBuilder:shouldShow(param_names)
function InfoboxBuilder:shouldShow(paramNames)
if param_names and #param_names > 0 then
if paramNames and #paramNames > 0 then
local actual_values = {}
local actualValues = {}
for i,v in ipairs(param_names) do
for _, name in ipairs(paramNames) do
table.insert(actual_values, self:getContent(v))
table.insert(actualValues, self.procArgs[name])
end
end
if #actual_values == 0 then
if #actualValues == 0 then
return false
return false
end
end
Line 260: Line 314:
return true
return true
end
end



--- Adds a header
--- Adds a header
-- @param arg { content, attr, colspan, rowspan, css }
-- @param arg { tag, content, attr, colspan, rowspan, css }
-- content string or nil
-- tag "argth" or "th"
-- The wikitext to be rendered
-- Whether or not an it is based off a parameter
-- content string or {...} or nil
-- The wikitext to be rendered if th, and the parameter(s) if
-- argth
-- fn function
-- A function that turns processed arg(s) into their final
-- display format.
-- attr {...} or nil
-- attr {...} or nil
-- The attributes of the cell in table form
-- The attributes of the cell in table form
-- colspan number or nil
-- colspan number or nil
-- The colspan of the cell
-- The colspan of the cell
-- roswpan number or nil
-- rowspan number or nil
-- The rowspan of the cell
-- The rowspan of the cell
-- css {...} or nil
-- css {...} or nil
-- The css of the cell in table form
-- The css of the cell in table form
-- @param options { hideIfEmpty }
-- @param options { hideIfEmpty, subheader }
-- hideIfEmpty { param_name, ... }
-- hideIfEmpty { paramName, ... }
-- param_name string
-- paramName string
-- The param_name that will be used to check if corresponding
-- The parameter name that will be used to check if the
-- content is nil
-- corresponding content is nil
-- subheader boolean
-- Whether the header is a subheader or not
-- @return self
-- @return self
-- The current object
-- The current object
function InfoboxBuilder:addHeader(arg, options)
function InfoboxBuilder:addHeader(arg, options)
local isSubheader = false
if options then
if options then
if not self:shouldShow(options.hideIfEmpty) then
if not self:shouldShow(options.hideIfEmpty) then
return self
return self
end
end
if options.subheader then
isSubheader = true
end
end
end
self:addSpacer()
local _cell = self.infobox:tag('tr'):tag('th'):attr('colspan', 30)
local ibCell = mw.html.create('tr')
:tag('th')
_cell:css({
:attr('colspan', 30)
['text-align'] = 'center',
['background-color'] = self.headerColors.bg,
:css(self.headerColors)
['color'] = self.headerColors.text
if not isSubheader then
})
ibCell:addClass('infobox-header')
else
ibCell:addClass('infobox-subheader')
end
if arg.attr then
if arg.attr then
_cell:attr(arg.attr)
ibCell:attr(arg.attr)
end
end
if arg.colspan then
if arg.colspan then
_cell:attr('colspan', arg.colspan)
ibCell:attr('colspan', arg.colspan)
end
end
if arg.rowspan then
if arg.rowspan then
_cell:attr('rowspan', arg.rowspan)
ibCell:attr('rowspan', arg.rowspan)
end
end
if arg.css then
if arg.css then
_cell:css(arg.css)
ibCell:css(arg.css)
end
end
if arg.tag == 'th' then
if arg.tag == 'th' then
_cell:wikitext(arg.content)
ibCell:wikitext(arg.content)
elseif arg.tag == 'argth' then
elseif arg.tag == 'argth' then
_cell:wikitext(self:getContent(arg.content))
ibCell:wikitext(self:getContent(arg.content, arg.fn))
end
end
self:addSpacer()
self.infobox:node(ibCell)
self:addSpacer()
self:addSpacer()
Line 322: Line 391:


--- Adds an image, or switchable images
--- Adds an image, or switchable images
-- @param cols { { tag, content, title }, ... }
-- @param cols { { tag, content, fn, tabName }, ... }
-- tag "artd" or "td"
-- tag "argtd" or "td"
-- Whether or not an it is based off a parameter
-- Whether or not an it is based off a parameter
-- content string
-- content string or {...}
-- The content or the parameter name
-- The wikitext content if td or parameter name(s) if argtd
-- title string or nil
-- fn function
-- The title, if using switchable images
-- A function that turns processed arg(s) into their final
-- display format.
-- tabName string or nil
-- The tab name, if using switchable images
-- required boolean or nil
-- Whether or not the tab will show regardless if empty or not
-- @param options { hideIfEmpty }
-- @param options { hideIfEmpty }
-- hideIfEmpty { param_name, ... }
-- hideIfEmpty { paramName, ... }
-- param_name string
-- paramName string
-- The param_name that will be used to check if corresponding
-- The parameter name that will be used to check if the
-- content is nil
-- corresponding content is nil
-- @return self
-- @return self
-- The current object
-- The current object
Line 343: Line 417:
end
end
local _cell = self.infobox:tag('tr'):tag('td'):css('text-align', 'center')
local ibCell = mw.html.create('tr')
:tag('td')
local content = '?'
:addClass('infobox-image')
:attr('colspan', 30)
local actual_args = {}
local content = nil
for _,v in ipairs(cols) do
local c = v.content
local actualArgs = {}
for _, col in ipairs(cols) do
if v.tag == 'argtd' then
content = col.content
c = self:getContent(c)
if col.tag == 'argtd' then
content = self:getContent(content, col.fn)
end
end
if c ~= nil then
if content == nil and col.required == true then
table.insert(actual_args, { title = v.title, content = c })
table.insert(
actualArgs,
{
tabName = col.tabName,
content = string.format(
'<span class="plainlinks">[%s?action=edit ? (edit)]</span>',
tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
)
}
)
end
if content ~= nil then
table.insert(actualArgs, { tabName = col.tabName, content = content })
end
end
end
end
if #actual_args == 0 then
if #actualArgs == 0 then
ibCell:addClass('plainlinks')
return self

elseif #actual_args < 2 then
content = actual_args[1].content
content = string.format(
'[%s?action=edit ? (edit)]',
tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
)
elseif #actualArgs == 1 then
content = actualArgs[1].content
else
else
local t = {}
local tabs = {}
for _,v in ipairs(actual_args) do
for _, actArg in ipairs(actualArgs) do
table.insert(t, v.title .. '=' .. v.content)
table.insert(tabs, actArg.tabName .. '=' .. actArg.content)
end
end
content = mw.getCurrentFrame():callParserFunction({
content = mw.getCurrentFrame()
:callParserFunction({
name = '#tag',
args = { 'tabber', table.concat(t, '|-|') }
name = '#tag',
args = { 'tabber', table.concat(tabs, '|-|') }
})
})
end
end
ibCell:wikitext(content or '?')
_cell:attr('colspan', 30)
_cell:wikitext(content)
self.infobox:node(ibCell)
return self
return self
Line 381: Line 479:


--- Adds a row, with columns up to 30 columns spanned
--- Adds a row, with columns up to 30 columns spanned
-- @param cols { { tag, content, hide, attr, colspan, rowspan, css }, ... }
-- @param cols { { tag, content, fn, attr, colspan, rowspan, css, class, cssFuncs, classFuncs }, ... }
-- tag "th", "td", "argth", "argtd"
-- tag "th", "td", "argth", "argtd"
-- A string containing one of the above, "th" or "td" uses
-- A string containing one of the above, "th" or "td" uses
-- content as the wikitext, "argth" or "argtd" uses content as
-- content as the wikitext, "argth" or "argtd" uses content as
-- the parameter name to produce the suitable content
-- the parameter name to produce the suitable content
-- content string
-- content string or {...}
-- Content to be used as wikitext or a parameter name
-- Content to be used as wikitext or a parameter name for fn
-- attr {...} or nil
-- fn function or nil
-- The attributes of the cell in table form
-- A function that turns processed arg(s) into their final
-- colspan number or nil
-- display format.
-- The colspan of the cell
-- attr {...} or nil
-- The attributes of the cell in table form
-- rowspan number or nil
-- The rowspan of the cell
-- colspan number or nil
-- css {...} or nil
-- The colspan of the cell
-- The css of the cell in table form
-- rowspan number or nil
-- The rowspan of the cell
-- @param options { hideIfEmpty }
-- hideIfEmpty { param_name, ... }
-- css {...} or nil
-- The css of the cell in table form
-- param_name string
-- class {...} or nil
-- The param_name that will be used to check if corresponding
-- content is nil
-- The classes of the cell in table form or the class of the
-- cell in string form
-- cssFns { fn , ... } or nil
-- fn function
-- A function that returns css in table form
-- classFns { fn, ... } or nil
-- fn function
-- A function that returns css classes as a table or returns
-- a css class as a table
-- @param options { hideIfEmpty, defaultCss }
-- hideIfEmpty { paramName, ... }
-- paramName string
-- The parameter name that will be used to check if the
-- corresponding content is nil
-- defaultCss {...} or nil
-- The css of all cells in table form
-- @return self
-- @return self
-- The current object
-- The current object
function InfoboxBuilder:addRow(cols, options)
function InfoboxBuilder:addRow(cols, options)
local defaultCss = nil
if options then
if options then
if not self:shouldShow(options.hideIfEmpty) then
if not self:shouldShow(options.hideIfEmpty) then
return self
return self
end
end
if options.defaultCss then
defaultCss = options.defaultCss
end
end
end
local _row = self.infobox:tag('tr')
local ibRow = self.infobox:tag('tr')
for i,v in ipairs(cols) do
local colspans = {}
local _cell = _row:tag(tagmap[v.tag] or 'td')
if #cols == 2 then
:attr('colspan', 30 / #cols)
colspans = { 12, 18 }
end
for i, col in ipairs(cols) do
local ibCell = ibRow:tag(tagmap[col.tag] or 'td')
:attr('colspan', colspans[i] or (30 / #cols))
if v.attr then
if col.attr then
_cell:attr(v.attr)
ibCell:attr(col.attr)
end
end
if v.colspan then
if col.colspan then
_cell:attr('colspan', v.colspan)
ibCell:attr('colspan', col.colspan)
end
end
if v.rowspan then
if col.rowspan then
_cell:attr('rowspan', v.rowspan)
ibCell:attr('rowspan', col.rowspan)
end
end
if v.css then
if defaultCss then
_cell:css(v.css)
ibCell:css(defaultCss)
end
if col.css then
ibCell:css(col.css)
end
if col.class then
if type(col.class) == 'table' then
for _, c in ipairs(coll.class) do
ibCell:addClass(c)
end
else
ibCell:addClass(c)
end
end
end
if v.tag == 'th' or v.tag == 'td' then
if col.tag == 'th' or col.tag == 'td' then
_cell:wikitext(v.content)
ibCell:wikitext(col.content)
elseif v.tag == 'argth' or v.tag == 'argtd' then
elseif col.tag == 'argth' or col.tag == 'argtd' then
local content = self:getContent(v.content)
local content = self:getContent(col.content, col.fn)
if content then
if content ~= nil then
if col.cssFns and #col.cssFns > 0 then
_cell:wikitext(content)
for _, fn in ipairs(col.cssFns) do
local cellCss = fn(self.procArgs[col.content])
if cellCss then
ibCell:css(cellCss)
end
end
end
if col.classFns and #col.classFns > 0 then
for _, fn in ipairs(col.classFns) do
local cellClasses = fn(self.procArgs[col.content])
if cellClasses then
if type(cellClasses) == 'table' then
for _, class in ipairs(cellClasses) do
ibCell:addClass(class)
end
else
ibCell:addClass(cellClasses)
end
end
end
end
ibCell:wikitext(content)
else
else
_cell:tag('span'):addClass('plainlinks')
ibCell:addClass('plainlinks')
:wikitext(
:wikitext(
string.format("[%s?action=edit ? (edit)]",
string.format(
'[%s?action=edit ? (edit)]',
tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
)
)
)
)
end
end
end
end
Line 454: Line 614:
spacer:tag('td')
spacer:tag('td')
:attr('colspan', 1)
:attr('colspan', 1)
:addClass('spacer-cell')
:css('width', 'calc(100% / 30)')
end
end
end
end
Line 463: Line 623:
self.finished = true
self.finished = true
self:addRow({{
local links = {
tag = 'td',
"[[Template:%s|<span style=\"color: %s;\">View</span>]]",
content = Navbar({ self.name, plain = 1, noedit = 1 }),
"[[Template talk:%s|<span style=\"color: %s;\">Talk</span>]]"
colspan = 30
}
}})
self:addHeader{
tag = 'th',
content =
string.format(links[1], self.name, self.headerColors.text)
.. " &bull; " ..
string.format(links[2], self.name, self.headerColors.text)
}
end
end
end
end
Line 487: Line 641:
self.finished = true
self.finished = true
return tostring(self.infobox)
return
mw.getCurrentFrame():extensionTag{
name = 'templatestyles',
args = { src = 'Module:InfoboxBuilder/styles.css' }
} ..
tostring(self.infobox)
end
end



Latest revision as of 16:41, 29 March 2023

This module creates an infobox using the builder pattern. All infoboxes using this module can be found at Category:Infobox modules.

Building an infobox[edit source]

For an infobox to be built without errors, certain essential functions must be called before others. The following table details groups of functions and their priorities. The lower the number, the higher the priority. The functions setHeaderTextColor() and setHeaderBackgroundColor() are not required, but their CSS changes will not be applied if called later. In addition, the functions that add rows to the table, addHeader(), addImage(), and addRow() are not all required, but is it recommended to use at least addHeader() and addRow().

Core function priority
Priority Functions
1
  • new
2
  • setParams
  • setArgs
3
  • processArgs
4
  • setHeaderTextColor
  • setHeaderBackgroundColor
5
  • setName
  • addHeader
  • addImage
  • addRow
6
  • tostring

Import the module[edit source]

local InfoboxBuilder = require('Module:InfoboxBuilder')

Unpack the frame arguments[edit source]

function p.main(frame)
	local args = frame:getParent().args
	...

Create the infobox object[edit source]

local infobox = InfoboxBuilder.new()

Set the infobox name[edit source]

Setting the infobox name sets the template that the infobox links to inside of the navbar.

infobox:setName('Infobox')

Define the parameters[edit source]

When defining the parameters, the arguments will be processed when given a function or table. fn is an optional processing function or table that will transform the raw argument value into a specific format. An optional default value for the raw argument can be set using the default option.

An example of using fn would be to have fn be a function that splits a comma separated list into a table in Lua.

infobox:setParams {
	...
}

Pass in the arguments[edit source]

infobox:setArgs(args)

Process the arguments[edit source]

Processing the arguments will set default value (if it exists) and turn the raw argument passed in from setArgs(args) into a processed format for each parameter. This step is required or else the infobox will not work.

infobox:processArgs()

Specify a category map[edit source]

A category map can be optionally set. This uses the processed argument and generates the correct categories.

infobox:setCategoryMap({
	...
})

Prepare[edit source]

Create the look of the infobox by adding headers, images, or rows. If the values shown in these cells use values from parameters, an optional postprocessing function or table fn will transform the processed arguments for display purposes.

-- add a header or subheader
infobox:addHeader(
	{...},
	{...}
)

-- add an image
infobox:addImage(
	{...},
	{...}
)

-- add a row
infobox:addRow(
	{...},
	{...}
)

Build[edit source]

To build the infobox from data into an HTML table, call the tostring() function.

infobox:tostring()

Get the categories from the category map[edit source]

To get the categories, call the getCategories() function.

infobox:getCategories()

Functions[edit source]

For the following functions, assume an InfoboxBuilder object called "infobox" already exists.

local infobox = InfoboxBuilder.new()

Public functions[edit source]

new[edit source]

This function is required.

InfoboxBuilder.new()

Creates a new InfoboxBuilder object.

↓ Jump to definition

setName[edit source]

This function is required.
This function is chainable.

infobox:setName(arg)
arg

arg should be a string. Setting the infobox name will link the navbar to the correct template page and template talk page.

↓ Jump to definition

setHeaderTextColor[edit source]

This function is optional.
This function is chainable.

infobox:setHeaderTextColor(arg)
arg

arg should be a string that contains a valid CSS color (hex code, rgb value, hsl value, etc.). Calling this function will change the color of the text in the infobox's headers and subheaders. The changes will not apply to headers added before this function is called, so it is recommended to call this function early.

↓ Jump to definition

setHeaderBackgroundColor[edit source]

This function is optional.
This function is chainable.

infobox:setHeaderBackgroundColor(arg)
arg

arg should be a string that contains a valid CSS color (hex code, rgb value, hsl value, etc.). Calling this function will change the background color of the infobox's headers and subheaders. The changes will not apply to headers added before this function is called, so it is recommended to call this function early.

↓ Jump to definition

setParams[edit source]

This function is required.
This function is chainable.

infobox:setParams(...)

This function sets the valid parameters, their default values, and their formatting.

The arguments passed in should be tables of format:

{
	name = <paramName>,
	fn = <processingFn>,
	default = <default>
}
paramName

paramName should be a valid string that is unique. This name serves the key used to grab the raw values from the args table passed in from setArgs(). It also serves as the key for each parameter and will be referenced later.

processingFn

processingFn should be a function or a table that transforms the raw value of the argument passed in. This value is optional.

A collection of predefined processing functions can be found at Module:ProcessingFunctions.

default

default should be a string that serves as the default value if no raw value is present for the key in the args table. This value is optional.

↓ Jump to definition

setArgs[edit source]

This function is required.
This function is chainable.

infobox:setArgs(args)
args

args should be a table with key value pairs representing parameter names and values.

↓ Jump to definition

getRawArgs[edit source]

infobox:getRawArgs()

This function returns the "private" rawArgs associative array containing the raw values passed in from setArgs().

↓ Jump to definition

getProcessedArgs[edit source]

infobox:getProcessedArgs()

This function returns the "private" procArgs associative array after being processed.

↓ Jump to definition

getArgs[edit source]

infobox:getArgs(which)
which

which should be a string that is either "raw" or "processed" for the raw argument values or processed argument values, respectively.

This function returns the "private" rawArgs or procArgs associative arrays depending on the value of which.

↓ Jump to definition

setCategoryMap[edit source]

This function is optional.
This function is chainable.

infobox:setCategoryMap(catMap)
catMap

catMap should be a table of tables, where the key of the outer table corresponds with a parameter name and the key of the inner tables correspond with possible values of the associated parameter. The inner table values should be the category name related to each parameter value.

↓ Jump to definition

getCategories[edit source]

infobox:getCategories()

This function returns a string with autogenerated categories in wikitext form.

↓ Jump to definition

processArgs[edit source]

This function is required.
This function is chainable.

infobox:processArgs()

This function processes the all the arguments passed in with the given processing functions defined when setting parameters.

↓ Jump to definition

addHeader[edit source]

This function is optional, but recommended.
This function is chainable.

infobox:addHeader(arg, options)

This functions adds a header or subheader to the infobox, depending on the option set.


arg

arg should be a table of the following format:

{
	tag = <tag>,
	content = <content>,
    fn = <displayFn>,
	attr = <attr>,
	colspan = <colspan>,
	rowspan = <rowspan>,
	css = <css>
}
tag

tag should be a string of value "argth" or "th".

content

When tag is set to "th", content should contain the wikitext that will show up.

When tag is set to "argth", content should be a string or table of parameter names. This value will be passed into displayFn if it is set.

displayFn

displayFn should be a function that transforms one or more processed arguments (based on content into something that can be displayed (ex. an HTML list). The order of the parameters in this function is the same as the order of content, if content is a table. This value is optional.

A collection of predefined display functions can be found at Module:DisplayFunctions.

attr

attr should be a table containing HTML attributes. The value gets passed into the mw.html:attr() function. This value is optional.

colspan

colspan should be a number or string denoting the number of columns this header spans. This value is optional.

rowspan

rowspan should be a number or string denoting the number of rows this header spans. This value is optional.

css

css should be a table of CSS names and values. The value gets passed into the mw.html:css() function. This value is optional.


options

options should be a table of the following format:

{
	hideIfEmpty = <hideIfEmpty>,
	subheader = <subheader>
}
hideIfEmpty

hideIfEmpty should be a table containing strings of parameter names. If all values for those parameters are empty, then the header or subheader is hidden. This value is optional.

subheader

subheader should be a boolean denoting whether the header should be a subheader or not. The default value is false. This value is optional.

↓ Jump to definition

addImage[edit source]

This function is optional, but recommended.
This function is chainable.

infobox:addImage(cols, options)

This function adds a single image or multiple images inside of a row. For multiple images, it selectively hides all but one image using TabberNeue.


cols

cols should be a table that is a numeric array. Each entry in this table should have the following format:

{
	tag = <tag>,
	content = <content>,
    fn = <displayFn>,
	tabName = <tabName>,
    required = <required>
}
tag

tag should be a string of value "argtd" or "td".

content

When tag is set to "td", content should be a string that shows up as the wikitext.

When tag is set to "argtd", content should be a string or table of parameter names. This value will be passed into displayFn if it is set.

displayFn

displayFn should be a function that transforms one or more processed arguments (based on content into something that can be displayed (ex. an HTML list). The order of the parameters in this function is the same as the order of content, if content is a table. This value is optional.

tabName

tabName should be a string if there are multiple images. The value of this does nothing if there's only one image.

required

required should be a boolean if the tab is required. This means that even if no value is provided, the tab will show up with a '?'.


options

options should be a table of the following format:

{
	hideIfEmpty = <hideIfEmpty>
}
hideIfEmpty

hideIfEmpty should be a tablecontaining strings of parameter names. If all values for those parameters are empty, then the image section is hidden. This value is optional.

↓ Jump to definition

addRow[edit source]

This function is optional, but recommended.
This function is chainable.

infobox:addRow(cols, options)

This function adds anywhere from 1 to 30 cells to a row. The colspan for each cell is automatically set to be evenly split so that all cells are the same width. The exception is when there are two cells, where the first cell spans 12 columns and the second cell spans 18 cells.


cols

cols should be a table that is a numeric array. Each entry in this table should have the following format:

{
	tag = <tag>,
	content = <content>,
    fn = <displayFn>,
	attr = <attr>,
	colspan = <colspan>,
	rowspan = <rowspan>,
	css = <css>,
	class = <class>,
	cssFns = <cssFns>,
	classFns = <classFns>
}
tag

tag should be a string of value "argth", "argtd", "th", or "td".

content

When tag is set to "td" or "th", content should contain the wikitext that will show up.

When tag is set to "argtd" or "argth", content should be a string or table of parameter names. This value will be passed into displayFn if it is set.

displayFn

displayFn should be a function that transforms one or more processed arguments (based on content into something that can be displayed (ex. an HTML list). The order of the parameters in this function is the same as the order of content, if content is a table. This value is optional.

A collection of predefined display functions can be found at Module:DisplayFunctions.

attr

attr should be a table containing HTML attributes. The value gets passed into the mw.html:attr() function. This value is optional.

colspan

colspan should be a number or string denoting the number of columns this header spans. This value is optional.

rowspan

rowspan should be a number or string denoting the number of rows this header spans. This value is optional.

css

css should be a table of CSS names and values. The value gets passed into the mw.html:css() function. This value is optional.

class

class should be either a string with a class name or table (numeric array) containing class names. Each class name gets passed into the mw.html:addClass() function. This value is optional.

cssFns

cssFns should be a table of functions. Each function takes the processed value of parameter content as input and should output a valid CSS table. This value only applies to cells with tag "argth" or "argtd". This value is optional.

classFns

classFns should be a table of functions. Each function takes the processed value of parameter content as input and should output a class name string. This value only applies to cells with tag "argth" or "argtd". This value is optional.


options

options should be a table of the following format:

{
	hideIfEmpty = <hideIfEmpty>,
	defaultCss = <defaultCss>
}
hideIfEmpty

hideIfEmpty should be a table containing strings of parameter names. If all values for those parameters are empty, then the cell is hidden. This value is optional.

defaultCss

defaultCss should be a table of CSS names and values. This CSS applies to all cells in this row. This value is optional.

↓ Jump to definition

tostring[edit source]

This function is required.

infobox:tostring()

This function "finishes" the infobox and returns an output HTML table with all styles automatically applied from Template:Infobox/styles.css. In order to generate an infobox, this function must be called.

↓ Jump to definition

Private functions[edit source]

While these are not necessarily "private", these functions are not intended to be called externally.

getContent[edit source]

infobox:getContent(paramName)

Gets the content for display for a specified parameter. If the value for a parameter has not been postprocessed, then the dFunc for that parameter, if it exists, will be called.

↓ Jump to definition

shouldShow[edit source]

infobox:shouldShow(paramNames)

This is a helper function to tell if a certain cell should be visible depending on the parameter names given. If all values for the parameters given have no value, then a cell should not show.

↓ Jump to definition

addSpacer[edit source]

infobox:addSpacer()

This function sets up the 30 column layout by inserting an empty row. It also serves as a spacer.

↓ Jump to definition

addLinks[edit source]

infobox:addLinks()

This function adds the navbar at the end of the infobox. This navbar contains links to the template page and the template talk page for this infobox. This uses the page using the value passed in from the setName() function.

↓ Jump to definition


-----------------------------------------------------------------------
--                       InfoboxBuilder v1.1.1                       --
-----------------------------------------------------------------------
-- Builds an infobox using Lua
--
-- Dependencies:
-- * Extensions
-- ** TemplateStyles
-- ** Tabber/TabberNeue
-- * Modules
-- ** Navbar
-- * Styles
-- ** Module:InfoboxBuilder/styles.css

local Navbar = require('Module:Navbar')._navbar

local InfoboxBuilder = {}
InfoboxBuilder.__index = InfoboxBuilder
InfoboxBuilder.__tostring = InfoboxBuilder.tostring

local tagmap = {
	th = 'th',
	td = 'td',
	argth = 'th',
	argtd = 'td'
}

--- Create the infobox
-- @return obj metatable
--             A metatable describing the infobox
function InfoboxBuilder.new()
	local obj = setmetatable({
		name = '',
		headerColors = {
			['color']            = nil,
			['background-color'] = nil
		},
		params = {},
		paramNames = { 'bg color', 'text color' },
		rawArgs = {},
		procArgs = {},
		categoryMap = {},
		infobox = mw.html.create('table')
			:addClass('infobox')
			:css('width', '330px'),
		finished = false
	}, InfoboxBuilder)

	return obj
end

--- Set the infobox name, for use with bottom links
-- @param arg string
--            Name of the template, not nil or empty
-- @return self
--         The current object
function InfoboxBuilder:setName(arg)
	if arg == nil or arg == '' then
		error('Template name must not be nil or empty')
	end
	
	self.name = arg
	
	return self
end

--- Set the text color of the header
-- @param arg string
--            Text color of the header, should be a valid value for the CSS 
--            "color" property, not nil or empty
-- @return self
--         The current object
function InfoboxBuilder:setHeaderTextColor(arg)
	if arg == nil or arg == '' then
		error('Header text color must not be nil or empty')
	end
	
	self.headerColors['color'] = arg
	
	return self
end

--- Set the background color of the header
-- @param arg string
--            Background color of the header, should be a valid value for the 
--            CSS "background-color" property, not nil or empty
-- @return self 
--         The current object
function InfoboxBuilder:setHeaderBackgroundColor(arg)
	if arg == nil or arg == '' then
		error('Header background color must not be nil or empty')
	end
	
	self.headerColors['background-color'] = arg
	
	return self
end

--- Sets the infobox params
-- @param ... {{ name, fn, default }, ...}
--        name    string
--                The name of the parameter, not nil, cannot be duplicate
--        fn      A function or table that processes the raw arguments
--                - A function that accepts the parameter as an argument and
--                  returns a string or list, OR
--                - A table that has the parameter as a key
--        default string or nil
--                The default value if no argument is given
-- @return self
--         The current object
function InfoboxBuilder:setParams(...)
	for _, p in ipairs(...) do
		if p.name == nil or p.name == '' then
			error('Param name must not be nil or empty')
		end
		if self.paramNames[p.name] then
			error('Param name cannot be duplicate')
		end
		
		self.params[p.name] = {
			fn = p.fn,
			default = p.default
		}
		table.insert(self.paramNames, p.name)
	end
	
	return self
end

--- Sets the infobox arguments
-- @param args Frame
--             A frame object, passed in when invoked
-- @return self
--         The current object
function InfoboxBuilder:setArgs(args)
	for name, value in pairs(args) do
		if value ~= '' then
			self.rawArgs[name] = value
		end
	end
	
	if self.rawArgs['bg color'] then
		self:setHeaderBackgroundColor(self.rawArgs['bg color'])
	end
	if self.rawArgs['text color'] then
		self:setHeaderTextColor(self.rawArgs['text color'])
	end
	
	return self
end

--- Gets the raw argument values passed
-- @return args table
--              A table containing the args
function InfoboxBuilder:getRawArgs()
	return self.rawArgs
end

--- Gets the argument values after being processed
-- @return args table
--              A table containing the args
function InfoboxBuilder:getProcessedArgs()
	return self.procArgs
end

--- Gets the argument values of the table, for either raw or processed
-- @param which string
--              A string that determines which argument values to return
-- @retun args table
--             A table containing the args
function InfoboxBuilder:getArgs(which)
	if which == 'raw' then
		return self:getRawArgs()
	elseif which == 'processed' then
		return self:getProcessedArgs()
	end
	
	return {}
end

--- Sets the category map for each param
-- @param catMap
-- @return self
--         The current object
function InfoboxBuilder:setCategoryMap(catMap)
	if catMap and type(catMap) == 'table' then
		self.categoryMap = catMap
	end
	
	return self	
end

--- Returns categories based on processed args
-- @return categories string
--                    A string containing with all the categories
function InfoboxBuilder:getCategories()
	local categories = {}
	for name, value in pairs(self.procArgs) do
		local catMap = self.categoryMap[name]
		
		local valueType = type(value)
		
		if catMap then
			if valueType == 'string' or 
			valueType == 'boolean' or
			valueType == 'number' then
				if catMap[value] then
					table.insert(
						categories,
						string.format('[[Category:%s]]', catMap[value])
					)
				end
			elseif valueType == 'table' then
				for _, val in ipairs(value) do
					if catMap[val] then
						table.insert(
							categories,
							string.format('[[Category:%s]]', catMap[val])
						)
					end
				end
			end
		end
	end
	
	return table.concat(categories, '')
end

--- Processes raw args into a format usable by auto categorizer and display functions
-- @return self
--         The current object
function InfoboxBuilder:processArgs()
	for name, param in pairs(self.params) do
		local value = self.rawArgs[name] or param.default
		
		local fn = param.fn
		local fnType = type(fn)
		
		if value then
			if fnType == 'function' then
				value = fn(value)
			elseif fnType == 'table' then
				value = fn[value]
			end
		end
		
		self.procArgs[name] = value
	end
	
	return self
end

--- Gets the content associated with a parameter or parameters
-- @param paramNames string or {...}
--                   The param name(s), not nil or empty
-- @param fn         function
--                   A function that turns an array of processed args into a
--                   string. The order of parameters is identical to paramNames.
--                   Used to transform args into their final display format.
-- @return string content
--                A string containing the content
function InfoboxBuilder:getContent(paramNames, fn)
	if paramNames == nil then
		error('Params must not be nil')
	else
		if type(paramNames) == 'table' then
			if #paramNames == 0 then
				error('There must be more than one param used')
			end
		elseif type(paramNames) == 'string' then
			paramNames = { paramNames }
		end
	end
	local contents = {}
	
	for i, paramName in ipairs(paramNames) do
		if paramName == '' then
			error('Param name must not be empty')
		elseif self.params[paramName] == nil then
			error(string.format('No such param with name: %s', paramName))
		end
		
		-- Must assign by index to preserve nil
		contents[i] = self.procArgs[paramName]
	end
	
	local content = nil
	if type(fn) == 'function' then
		content = fn(unpack(contents))
	elseif #paramNames == 1 then
		content = contents[1]
	end
	
	return content
end

--- Determines if the row should be shown based of a list of param names
-- @param paramNames { paramName, ... }
--        paramName  string
--                   The param name
-- @return shouldShow boolean
function InfoboxBuilder:shouldShow(paramNames)
    if paramNames and #paramNames > 0 then
    	local actualValues = {}
	    for _, name in ipairs(paramNames) do
	        table.insert(actualValues, self.procArgs[name])
	    end
        
        if #actualValues == 0 then
            return false
        end
    end
    
    return true
end

--- Adds a header
-- @param arg { tag, content, attr, colspan, rowspan, css }
--        tag     "argth" or "th"
--                Whether or not an it is based off a parameter
--        content string or {...} or nil
--                The wikitext to be rendered if th, and the parameter(s) if 
--                argth
--        fn      function
--                A function that turns processed arg(s) into their final
--                display format.
--        attr    {...} or nil 
--                The attributes of the cell in table form
--        colspan number or nil
--                The colspan of the cell
--        rowspan number or nil
--                The rowspan of the cell
--        css     {...} or nil
--                The css of the cell in table form
-- @param options { hideIfEmpty, subheader }
--        hideIfEmpty { paramName, ... }
--        paramName string
--                  The parameter name that will be used to check if the
--                  corresponding content is nil
--        subheader boolean
--                  Whether the header is a subheader or not
-- @return self
--         The current object
function InfoboxBuilder:addHeader(arg, options)
	local isSubheader = false
    if options then
        if not self:shouldShow(options.hideIfEmpty) then
        	return self
        end
		if options.subheader then
			isSubheader = true
		end
    end
	
	local ibCell = mw.html.create('tr')
		:tag('th')
		:attr('colspan', 30)
		:css(self.headerColors)
	
	if not isSubheader then
		ibCell:addClass('infobox-header')
	else 
		ibCell:addClass('infobox-subheader')
	end
	
	if arg.attr then
		ibCell:attr(arg.attr)
	end
	if arg.colspan then
		ibCell:attr('colspan', arg.colspan)
	end
	if arg.rowspan then
		ibCell:attr('rowspan', arg.rowspan)
	end
	if arg.css then
		ibCell:css(arg.css)
	end
	
	if arg.tag == 'th' then
		ibCell:wikitext(arg.content)
	elseif arg.tag == 'argth' then
		ibCell:wikitext(self:getContent(arg.content, arg.fn))
	end
	
	self:addSpacer()
	self.infobox:node(ibCell)
	self:addSpacer()
	
	return self
end

--- Adds an image, or switchable images
-- @param cols { { tag, content, fn, tabName }, ... }
--        tag     "argtd" or "td"
--                Whether or not an it is based off a parameter
--        content string or {...}
--                The wikitext content if td or parameter name(s) if argtd
--        fn      function
--                A function that turns processed arg(s) into their final
--                display format.
--        tabName string or nil
--                The tab name, if using switchable images
--       required boolean or nil
--                Whether or not the tab will show regardless if empty or not
-- @param options { hideIfEmpty }
--        hideIfEmpty { paramName, ... }
--        paramName string
--                  The parameter name that will be used to check if the
--                  corresponding content is nil
-- @return self
--         The current object
function InfoboxBuilder:addImage(cols, options)
	if options then
        if not self:shouldShow(options.hideIfEmpty) then
        	return self
    	end
    end
	
	local ibCell = mw.html.create('tr')
		:tag('td')
		:addClass('infobox-image')
		:attr('colspan', 30)
	
	local content = nil
	
	local actualArgs = {}
	for _, col in ipairs(cols) do
		content = col.content
		if col.tag == 'argtd' then
			content = self:getContent(content, col.fn)
		end
		
		if content == nil and col.required == true then
			table.insert(
				actualArgs,
				{
					tabName = col.tabName,
					content = string.format(
						'<span class="plainlinks">[%s?action=edit ? (edit)]</span>',
						tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
					)
				}
			)
		end
		
		if content ~= nil then
			table.insert(actualArgs, { tabName = col.tabName, content = content })
		end
	end
	
	if #actualArgs == 0 then
		ibCell:addClass('plainlinks')

		content = string.format(
			'[%s?action=edit ? (edit)]',
			tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
		)
	elseif #actualArgs == 1 then
		content = actualArgs[1].content
	else
		local tabs = {}
		for _, actArg in ipairs(actualArgs) do
			table.insert(tabs, actArg.tabName .. '=' .. actArg.content)
		end
		
		content = mw.getCurrentFrame()
			:callParserFunction({
				name = '#tag',
				args = { 'tabber', table.concat(tabs, '|-|') }
			})
	end
	
	ibCell:wikitext(content or '?')
	
	self.infobox:node(ibCell)
	
	return self
end

--- Adds a row, with columns up to 30 columns spanned
-- @param cols    { { tag, content, fn, attr, colspan, rowspan, css, class, cssFuncs, classFuncs }, ... }
--        tag        "th", "td", "argth", "argtd"
--                   A string containing one of the above, "th" or "td" uses 
--                   content as the wikitext, "argth" or "argtd" uses content as
--                   the parameter name to produce the suitable content
--        content    string or {...}
--                   Content to be used as wikitext or a parameter name for fn
--        fn         function or nil
--                   A function that turns processed arg(s) into their final
--                   display format.
--        attr       {...} or nil
--                   The attributes of the cell in table form
--        colspan    number or nil
--                   The colspan of the cell
--        rowspan    number or nil
--                   The rowspan of the cell
--        css        {...} or nil
--                   The css of the cell in table form
--        class      {...} or nil
--                   The classes of the cell in table form or the class of the
--                   cell in string form
--        cssFns     { fn , ... } or nil
--        fn         function
--                   A function that returns css in table form
--        classFns   { fn, ... } or nil
--        fn         function
--                   A function that returns css classes as a table or returns
--                   a css class as a table
-- @param options { hideIfEmpty, defaultCss }
--        hideIfEmpty { paramName, ... }
--        paramName   string
--                    The parameter name that will be used to check if the
--                    corresponding content is nil
--        defaultCss  {...} or nil
--                    The css of all cells in table form
-- @return self
--         The current object
function InfoboxBuilder:addRow(cols, options)
	local defaultCss = nil
    if options then
        if not self:shouldShow(options.hideIfEmpty) then
        	return self
        end
		if options.defaultCss then
			defaultCss = options.defaultCss
		end
    end
	
	local ibRow = self.infobox:tag('tr')
	
	local colspans = {}
	if #cols == 2 then
		colspans = { 12, 18 }
	end
	
	for i, col in ipairs(cols) do
		local ibCell = ibRow:tag(tagmap[col.tag] or 'td')
						:attr('colspan', colspans[i] or (30 / #cols))
		
		if col.attr then
			ibCell:attr(col.attr)
		end
		if col.colspan then
			ibCell:attr('colspan', col.colspan)
		end
		if col.rowspan then
			ibCell:attr('rowspan', col.rowspan)
		end
		if defaultCss then
			ibCell:css(defaultCss)
		end
		if col.css then
			ibCell:css(col.css)
		end
		if col.class then
			if type(col.class) == 'table' then
				for _, c in ipairs(coll.class) do
					ibCell:addClass(c)
				end
			else
				ibCell:addClass(c)
			end
		end
		
		if col.tag == 'th' or col.tag == 'td' then
			ibCell:wikitext(col.content)
		elseif col.tag == 'argth' or col.tag == 'argtd' then
			local content = self:getContent(col.content, col.fn)
			if content ~= nil then
				if col.cssFns and #col.cssFns > 0 then
					for _, fn in ipairs(col.cssFns) do
						local cellCss = fn(self.procArgs[col.content])
						if cellCss then
							ibCell:css(cellCss)
						end
					end
				end
				
				if col.classFns and #col.classFns > 0 then
					for _, fn in ipairs(col.classFns) do
						local cellClasses = fn(self.procArgs[col.content])
						if cellClasses then
							if type(cellClasses) == 'table' then
								for _, class in ipairs(cellClasses) do
									ibCell:addClass(class)
								end
							else
								ibCell:addClass(cellClasses)
							end
						end
					end
				end
			
				ibCell:wikitext(content)
			else
				ibCell:addClass('plainlinks')
					:wikitext(
						string.format(
							'[%s?action=edit ? (edit)]',
							tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
						)
					)
			end
		end
	end
	
	return self
end

--- Creates the 30-col layout
function InfoboxBuilder:addSpacer()
	local spacer = self.infobox:tag('tr')
	for i=1,30,1 do
		spacer:tag('td')
			:attr('colspan', 1)
			:addClass('spacer-cell')
	end
end

--- Adds links to the bottom of the infobox
function InfoboxBuilder:addLinks()
	if not self.finished then
		self.finished = true
		
		self:addRow({{
			tag = 'td',
			content = Navbar({ self.name, plain = 1, noedit = 1 }),
			colspan = 30
		}})
	end
end

--- Generates the infobox
-- @return string
--         The html of the infobox
function InfoboxBuilder:tostring()
	if not self.finished then
		self:addLinks()
	end
	
	self.finished = true
	
	return 
		mw.getCurrentFrame():extensionTag{
			name = 'templatestyles',
			args = { src = 'Module:InfoboxBuilder/styles.css' }
		} ..
		tostring(self.infobox)
end

return InfoboxBuilder
Cookies help us deliver our services. By using our services, you agree to our use of cookies.