Module:Infobox

From Xenharmonic Wiki
Jump to navigation Jump to search

Documentation transcluded from /doc
Note: While this module should not be invoked directly, the use of its corresponding template (Template:Infobox) is not absolutely necessary.

On other templates that use or generate infoboxes, you can call _infobox (note the underscore in front). The infobox function (without the underscore) is used by Template:Infobox as a wrapper.

On other modules, you can include local infobox = require("Module:Infobox")._infobox at or near the top.

Icon-Todo.png Todo: Documentation

local getArgs = require("Module:Arguments").getArgs
local p = {}

--------------------------------------------------------------------------------
------------------------------- HELPER FUNCTIONS -------------------------------
--------------------------------------------------------------------------------

-- Infobox header with adjacent links
-- Adjacent links are placed on the sides of the title, with options for 0, 2,
-- or 8 links.
function p.infobox_header(title, adjacent_links)
	local header = ''
	if adjacent_links == nil then
		header = title
	elseif #adjacent_links == 2 then
		header = header
			.. "\n"
			.. '{| style="width: 100%;"\n'
			.. '|-\n'
			.. '| style="font-size: 0.75em;" | ' .. adjacent_links[1] .. '\n'
			.. '| style="width: 50%;" | ' .. title .. '\n'
			.. '| style="font-size: 0.75em;" | ' .. adjacent_links[2] .. '\n'
			.. '|}\n'
	elseif #adjacent_links == 8 then
		header = header
			.. "\n"
			.. '{| style="width: 100%;"\n'
			.. '|-\n'
			.. '| style="font-size: 0.75em;" | ' .. adjacent_links[1] .. '\n'
			.. '| style="font-size: 0.75em; width: 50%;" | ' .. adjacent_links[2] .. '\n'
			.. '| style="font-size: 0.75em;" | ' .. adjacent_links[3] .. '\n'
			.. '|-\n'
			.. '| style="font-size: 0.75em;" | ' .. adjacent_links[4] .. '\n'
			.. '| style="width: 50%;"  | ' .. title .. '\n'
			.. '| style="font-size: 0.75em;" | ' .. adjacent_links[5] .. '\n'
			.. '|-\n'
			.. '| style="font-size: 0.75em;" | ' .. adjacent_links[6] .. '\n'
			.. '| style="font-size: 0.75em; width: 50%;" | ' .. adjacent_links[7] .. '\n'
			.. '| style="font-size: 0.75em;" | ' .. adjacent_links[8] .. '\n'
			.. '|}\n'
	else
		header = title
	end
	
	return header
end

-- Row of an infobox
-- Infobox is set up as a Mediawiki table with two cols.
function p.infobox_row(row_content)
	local row = ""
	if #row_content > 1 then
		local caption = row_content[1]
		local text    = row_content[2]
		row = row
			.. '|-\n'
			.. '| style="text-align: right; padding-right: 0.25em;" | ' .. caption .. '\n'
			.. '| style="background-color: white; padding-left: 0.25em; font-weight: bold;" | ' .. text .. '\n'
	elseif #row_content == 1 then
		local text = row_content[1]
		row = row
			.. '|-\n'
			.. '| colspan="2" style="text-align: center;" | ' .. text .. '\n'
	end
	return row
end

--------------------------------------------------------------------------------
-------------------------------- MAIN FUNCTIONS --------------------------------
--------------------------------------------------------------------------------

-- Function to be called by other modules; also called by wrapper function
function p._infobox(args)
	local title = args["Title"] or "Infobox Title"
	local adjacent_links = args["Adjacent Links"]
	local rows = args["Rows"]
	
	-- Start of infobox; outer div and start of table
	local infobox = '<div style="'
		.. 'border: 1px solid #999; '
		.. 'margin: 0; '
		.. 'margin-left: 1em; '
		.. 'margin-bottom: 0.5em; '
		.. 'padding: 0.5em; '
		.. 'background-color: #f0f0f0; '
		.. 'min-width: 15em; '
		.. 'float: right; '
		.. 'max-width: 100%; '
		.. 'overflow: auto;">\n'
		
	-- Infobox table, starting with table
		.. '{| style="border-collapse: collapse; width: 100%;"\n'
		.. '|+ style="font-size: 105%; font-weight: bold; text-align: center;" | ' .. p.infobox_header(title, adjacent_links) .. '\n'
		
	-- For loop for populating entries
	for i = 1, #rows do
		infobox = infobox .. p.infobox_row(rows[i])
	end
	infobox = infobox .. "|}</div>"
	
	return infobox
end

-- Function to be #invoke'd
-- Wrapper function for template-based infoboxes
-- Modeled off of navbox
function p.infobox(frame)
	local args = getArgs(frame)
	
	-- Preprocess adjacent links
	-- If there are two adjacent links (such as with edos), then links will be
	-- placed on the left and right of the title:
	--		[Link 1] Title [Link 2]
	-- - Link 1 is previous, link 2 is next
	-- If there are eight adjacent links (such as with mosses), then links
	-- surround the title in a 3x3 grid:
	--		[Link 1] [Link 2] [Link 3]
	--		[Link 4]  Title   [Link 5]
	--		[Link 6] [Link 7] [Link 8]
	-- Individual links can be omitted. If at least one upper or lower link is
	-- present, then rows for those two sets of links are added. Having no links
	-- defaults to having only the title.
	local is_upper_lower_links_present = args["Upper Left Link"] ~= nil or args["Upper Link"] ~= nil or args["Upper Right Link"] ~= nil
		or args["Lower Left Link"] ~= nil or args["Lower Link"] ~= nil or args["Lower Right Link"] ~= nil
	local is_side_links_present  = args["Left Link"] ~= nil or args["Right Link"] ~= nil
	
	local adjacent_links = {}
	if is_upper_lower_links_present then
		table.insert(adjacent_links, args["Upper Left Link" ] or "")
		table.insert(adjacent_links, args["Upper Link"      ] or "")
		table.insert(adjacent_links, args["Upper Right Link"] or "")
	end
	if is_side_links_present then
		table.insert(adjacent_links, args["Left Link" ] or "")
		table.insert(adjacent_links, args["Right Link"] or "")
	end
	if is_upper_lower_links_present then
		table.insert(adjacent_links, args["Lower Left Link" ] or "")
		table.insert(adjacent_links, args["Lower Link"      ] or "")
		table.insert(adjacent_links, args["Lower Right Link"] or "")
	end
	args["Adjacent Links"] = adjacent_links
	
	-- Cleanup individual links, as they've been combined into one table
	args["Upper Left Link" ] = nil
	args["Upper Link"      ] = nil
	args["Upper Right Link"] = nil
	args["Left Link"       ] = nil
	args["Right Link"      ] = nil
	args["Lower Left Link" ] = nil
	args["Lower Link"      ] = nil
	args["Lower Right Link"] = nil
	
	-- Preprocess rows
	-- Set row count to 30, under the reasoning that an infobox may need more
	-- rows and/or headers. This may be increased to 40 if needed.
	local rows = {}
	for i = 1, 30 do
		local header = args["Header " .. i]
		local data   = args["Data "   .. i]
		
		local row = nil
		if (header == nil and data ~= nil) then
			row = {}
			table.insert(row, data)
		elseif (header ~= nil and data ~= nil) then
			row = {}
			table.insert(row, header)
			table.insert(row, data)
		end
		if row ~= nil then
			table.insert(rows, row)
		end
		
		-- Remove original entries as cleanup
		args["Header " .. i] = nil
		args["Data "   .. i] = nil
	end
	args["Rows"] = rows
	
	return p._infobox(args)
end

--------------------------------------------------------------------------------
------------------------------- LEGACY FUNCTIONS -------------------------------
--------------------------------------------------------------------------------

-- These functions are kept in the meantime to support older infoboxes and WILL
-- be entirely deleted later! Please switch to the new functions!

-- Original function signature, kept for legacy support (for now).
function p.build(title, entries, prev_link, next_link)
	local args = {
		["Adjacent Links"] = { (prev_link or ""), (next_link or "") },
		["Title"] = title,
		["Rows"] = entries,
	}

	return p._infobox(args)
end

-- Original 8-link function signature, pulled from infobox mos.
function p.build_multilink(title, entries, adjacent_links)
	local args = {
		["Adjacent Links"] = adjacent_links,
		["Title"] = title,
		["Rows"] = entries,
	}

	return p._infobox(args)
end

return p