Jump to content

Module:Columns

From Wikiversity

Used by templates {{Columns}}, {{Columns start}}, {{Columns span}}, {{Columns break}}, and {{Columns end}} to create content columns using HTML <div> tags and CSS column styles.

  • Function p.columns creates columns based on the given parameters for the given text.
  • Function p.columns_start starts a column block based on the given parameters for the text that follows.
  • Function p.columns_span adds given text to the current column block that spans all columns.
  • Function p.columns_manual starts a manual column based on the given parameters for the text that follows.
  • Function p.columns_break adds a column break and starts a new column based on the given parameters for the text that follows.
  • Function p.columns_end ends the current columns block.
Create auto-break columns with text:
{{#invoke:Columns|columns|<text>}}
{{#invoke:Columns|columns|<count>|<text>}}
{{#invoke:Columns|columns|<width>|<text>}}
{{#invoke:Columns|columns|count=<count>|text=<text>}}
{{#invoke:Columns|columns|width=<width>|text=<text>}}
{{#invoke:Columns|columns|columns=<width> and/or <count>|gap=<gap>|rule=<rule>|style=<style>|text=<text>}}

Start auto-break columns:
{{#invoke:Columns|columns_start}}
{{#invoke:Columns|columns_start|<count>}}
{{#invoke:Columns|columns_start|<width>}}
{{#invoke:Columns|columns_start|count=<count>}}
{{#invoke:Columns|columns_start|width=<width>}}
{{#invoke:Columns|columns_start|columns=<width> and/or <count>|gap=<gap>|rule=<rule>|style=<style>}}

Span columns with text:
{{#invoke:Columns|columns_span|<text>}}
{{#invoke:Columns|columns_span|text=<text>}}

Start manual-break columns:
{{#invoke:Columns|columns_manual}}
{{#invoke:Columns|columns_manual|<width>}}
{{#invoke:Columns|columns_manual|width=<width>|style=<style>}}

Add manual column break:
{{#invoke:Columns|columns_break}}
{{#invoke:Columns|columns_break|<width>}}
{{#invoke:Columns|columns_break|width=<width>|style=<style>}}

End columns:
{{#invoke:Columns|columns_end}}

local getArgs = require('Module:Arguments').getArgs

local p = {}

local class = {}
local style = {}
local text = {}
local add_default = true

-- _class processes class.
local function _class(value)
	if value == nil or value == "" then
		return ""
	end

	class[#class + 1] = "class='"
	class[#class + 1] = value
	class[#class + 1] = "' "
end

-- _append_style appends the given property and value to the style table.
local function _append_style(property, value)
	style[#style + 1] = property
	style[#style + 1] = ":"
	style[#style + 1] = value
	style[#style + 1] = ";"
end

-- _text processes text.
local function _text(value)
	if value == nil or value == "" then
		return
	end

	text[#text + 1] = value
end

-- _columns processes columns.
local function _columns(value)
	if value == nil or value == "" then
		return
	end

	-- Treat long unnamed parameters as content.
	if string.len(value) >= 10 then
		_text(value)
		return
	end

	_append_style("-webkit-columns", value)
	_append_style("-moz-columns", value)
	_append_style("columns", value)
	add_default = false
end

-- _count processes column-count.
local function _count(value)
	if value == nil or value == "" then
		return
	end

	if tonumber(value) == nil and value ~= "auto" then
		error("Parameter error - count must be a number or 'auto'.")
	end
	
	_append_style("-webkit-column-count", value)
	_append_style("-moz-column-count", value)
	_append_style("column-count", value)
	add_default = false
end

-- _end_tag returns the div end tag.
local function _end_tag()
	return "</div></div>"
end

-- _gap processes column-gap.
local function _gap(value)
	if value == nil or value == "" then
		return
	end

	_append_style("-webkit-column-gap", value)
	_append_style("-moz-column-gap", value)
	_append_style("column-gap", value)
end

-- _rule processes column-rule.
local function _rule(value)
	if value == nil or value == "" then
		return
	end

	_append_style("-webkit-column-rule", value)
	_append_style("-moz-column-rule", value)
	_append_style("column-rule", value)
end

-- _rules processes Div_col rules default value.
local function _rules(value)
	if string.lower(value) == "yes" then
		_rule("1px solid #AAA")
	end
end

-- _rule_color processes column-rule-color.
local function _rule_color(value)
	if value == nil or value == "" then
		return
	end

	_append_style("-webkit-column-rule-color", value)
	_append_style("-moz-column-rule-color", value)
	_append_style("column-rule-color", value)
end

-- _rule_style processes column-rule-style.
local function _rule_style(value)
	if value == nil or value == "" then
		return
	end

	_append_style("-webkit-column-rule-style", value)
	_append_style("-moz-column-rule-style", value)
	_append_style("column-rule-style", value)
end

-- _rule_width processes column-rule-width.
local function _rule_width(value)
	if value == nil or value == "" then
		return
	end

	_append_style("-webkit-column-rule-width", value)
	_append_style("-moz-column-rule-width", value)
	_append_style("column-rule-width", value)
end

-- _start_tag returns the div start tag.
local function _start_tag()
	return "<div " .. table.concat(class) .. "style='" .. 
		table.concat(style) .. "'>"
end

-- _style processes style.
local function _style(value)
	if value == nil or value == "" then
		return
	end

	if string.sub(value, -1) ~= ";" then
		value = value .. ";"
	end

	style[#style + 1] = value
end

-- _small processes Div_col small default value.
local function _small(value)
	if string.lower(value) == "yes" then
		_style("font-size:90%;")
	end
end

-- _width processes column-width.
local function _width(value)
	if value == nil or value == "" then
		return
	end

	_append_style("-webkit-column-width", value)
	_append_style("-moz-column-width", value)
	_append_style("column-width", value)
	add_default = false
end

-- _columns_break processes Columns|columns_break.
local function _columns_break(args)
	local div = {
		"</div><div style='",
		"display:table-cell;",
		"padding: 0 1em 0 0;",
	}
	local width = nil
	
	if args.style ~= nil then
		div[#div + 1] = args.style
		if string.sub(args.style, -1) ~= ";" then
			div[#div + 1] = ";"
		end
	end

	if args[1] ~= nil then
		width = args[1]
	elseif args.width ~= nil then
		width = args.width
	end

	if width ~= nil then
		div[#div + 1] = "width:"
		div[#div + 1] = width
		if string.sub(width, -1) ~= ";" then
			div[#div + 1] = ";"
		end
	end

	div[#div + 1] = "'>"

	return table.concat(div) 
end

-- _columns_manual process Columns.|columns_manual.
local function _columns_manual(args)
	local div = {
		"<div style='",
		"display:table;",
		"table-layout:fixed;",
		"width:100%;",
		"'>",
		"<div style='",
		"display:table-cell;",
		"padding: 0 1em 0 0;",
		"'>"
	}

	-- TODO: Add width and style parameters.

	return table.concat(div)
end

-- _columns__span processes Columns|columns_span. 
-- Not supported in Firefox as of November 2016.
local function _columns_span(args)
	local parameters = {
		[1] = _text,
		['style'] = _style,
		['text'] = _text,
	}

	_style("-webkit-column-span:all;column-span:all;")
	
	for key, value in pairs(args) do
		if parameters[key] == nil then
			error("Unexpected parameter " .. key .. ".")
		end
		
		-- Call parameter function passing parameter value
		parameters[key](value)
	end

	return "<div " .. 
		table.concat(class) .. 
		"style='" .. 
		table.concat(style) .. 
		"'>" .. 
		table.concat(text) .. 
		"</div>"
end

-- _columns_start processes Columns|column_start.
function _columns_start(args)
	local parameters = {
		[1] = _columns,
		[2] = _columns,
		['columns'] = _columns,
		['count'] = _count, 
		['gap'] = _gap, 
		['rule'] = _rule,
		['rulecolor'] = _rule_color,
		['rulestyle'] = _rule_style,
		['rulewidth'] = _rule_width,
		['style'] = _style,
		['text'] = _text,
		['width'] = _width,
		['cols'] = _columns,      -- To replace Div_col template.
		['colwidth'] = _width,    -- To replace Div_col template.
		['rules'] = _rules,       -- To replace Div_col template.
		['small'] = _small        -- To replace Div_col template.
	}

	for key, value in pairs(args) do
		if parameters[key] == nil then
			error("Unexpected parameter " .. key .. ".")
		end
		
		-- Call parameter function passing parameter value
		parameters[key](value)
	end

	if add_default == true then
		_columns("2")
	end

	return _start_tag()
end

function p.columns(frame)
	return _columns_start(getArgs(frame)) .. 
		"<div>" ..
		table.concat(text) .. 
		_end_tag()
end

function p.columns_break(frame)
	return _columns_break(getArgs(frame))
end

function p.columns_manual(frame)
	return _columns_manual(getArgs(frame))
end

function p.columns_end(frame)
	return _end_tag()
end

function p.columns_span(frame)
	return _columns_span(getArgs(frame))
end

function p.columns_start(frame)
	return _columns_start(getArgs(frame)) .. 
		"<div>"
end

return p