Module:Sandbox/ChaoticShadow/InfoboxBuilder

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 = {			text = '#000',			bg  = 'transparent'		},		params = {},		paramnames = {},		args = {},		final_args = {},		proto_infobox = {},		infobox = mw.html.create('table'):addClass('infobox'),		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 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 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.text = 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.bg = 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 the infobox params -- @param ... {{ name, func, default }, ...} --       name    string --               The name of the parameter, not nil, cannot be duplicate --       func    function, table or string --               A function that accepts the parameter as an argument and --               returns a string, OR --                A table that has the parameter as a key, OR --                An empty string --       default string or nil --               The default value if no argument is given -- @return self --        The current object function InfoboxBuilder:setParams(...) for i, v in ipairs(...) do		if v.name == nil and v.name == "" then error("name must not be nil or empty") end if self.paramnames[v.name] then error("name cannot be duplicaate") end if type(v.func) ~= 'function' and type(v.func) ~= 'table' and type(v.func) ~= 'string' then error("func must be of type \"function\", \"table\", or \"string\"") end self.params[v.name] = { ['type'] = type(v.func), func = v.func, default = v.default }		table.insert(self.paramnames, v.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 k,v in pairs(args) do		self.args[k] = v	end return self end

--- Gets the content associated with a parameter -- @param param string --             The param name, not nil or empty -- @return content string --                A string containing the content function InfoboxBuilder:getContent(param) if param == nil or param == "" then error("Param must not be nil or empty") end local content = '?' local argparams = self.params[param] if argparams == nil then error(string.format("No such param: %s", param)) end local arg = self.args[param] or self.params[param].default if arg == nil then error("Error") end if argparams['type'] == 'function' then content = self.params[param].func(arg) elseif argparams['type'] == 'table' then content = self.params[param].func[arg] elseif argparams['type'] == 'string' then content = arg end return content end

--- Adds a header -- @param arg { content, attr, colspan, rowspan, css } --       content string or nil The wikitext to be rendered --       attr    {...} or nil  The attributes of the cell in table form --       colspan number or nil The colspan of the cell --       roswpan number or nil The rowspan of the cell --       css     {...} or nil  The css of the cell in table form -- @return self --        The current object function InfoboxBuilder:addHeader(arg) self:addSpacer local _cell = self.infobox:tag('tr'):tag('th'):attr('colspan', 30) _cell:css({		['text-align']      = 'center',		['background-color'] = self.headerColors.bg,		['color']            = self.headerColors.text	}) if arg.attr then _cell:attr(arg.attr) end if arg.colspan then _cell:attr('colspan', arg.colspan) end if arg.rowspan then _cell:attr('rowspan', arg.rowspan) end if arg.css then _cell:css(arg.css) end _cell:wikitext(arg.content) self:addSpacer return self end

--- Adds an image, or switchable images -- @param ... { { tag, content, title }, ... } --       tag     "artd" or "td" Whether or not an it is based off a parameter --       content string         The content or the parameter name --       title   string or nil  The title, if using switchable images -- @return self --        The current object function InfoboxBuilder:addImage(...) local argt = ... local _cell = self.infobox:tag('tr'):tag('td') local content = '?' -- local actual_args = {} -- for i,v in ipairs(argt) do	-- 	local c = v.content -- 	if v.tag == 'argtd' then -- 		c = self:getContent(c) -- 	end -- 	if c == nil then -- 	end -- 	table.insert(actual_args, i, c)	-- end if #argt < 2 then local v = argt[1] -- tables start at 1 content = v.content if v.tag == 'argtd' then content = self:getContent(content) end else local t = {} for i, v in ipairs(argt) do			local c = v.content if v.tag == 'argtd' then c = self:getContent(c) end table.insert(t, i, v.title .. "=" .. c)		end content = mw.getCurrentFrame:callParserFunction({					name = '#tag',					args = { 'tabber', table.concat(t, "|-|") }				}) end _cell:attr('colspan', 30) _cell:wikitext(content) return self end

--- Adds a row, with columns up to 30 columns spanned -- @param ... { { tag, content, hide, attr, colspan, rowspan, css }, ... } --       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        Content to be used as wikitext or a parameter --                             name --       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 -- @return self --        The current object function InfoboxBuilder:addRow(...) local _row = self.infobox:tag('tr') local argt = ... for i, v in ipairs(argt) do		local _cell = _row:tag(tagmap[v.tag] or 'td') :attr('colspan', 30 / #argt) if v.attr then _cell:attr(v.attr) end if v.colspan then _cell:attr('colspan', v.colspan) end if v.rowspan then _cell:attr('rowspan', v.rowspan) end if v.css then _cell:css(v.css) end if v.tag == 'th' or v.tag == 'td' then _cell:wikitext(v.content) elseif v.tag == 'argth' or v.tag == 'argtd' then _cell:wikitext(self:getContent(v.content)) 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) :css('width', 'calc(100% / 30)') end end

--- Adds links to the bottom of the infobox function InfoboxBuilder:addLinks if not self.finished then self.finished = true local links = { "View", "Talk" }		self:addHeader{ content = string.format(links[1], self.name) .. " &bull; " .. string.format(links[2], self.name) }	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 tostring(self.infobox) end

return InfoboxBuilder