Modulo:Navbox

Versione del 20 mar 2015 alle 13:49 di Rotpunkt (discussione | contributi) (aggiunto modulo No globals)

Il modulo Navbox implementa le funzionalità dei template {{Navbox}} e {{Navbox subgroup}}.

Ha due sottopagine CSS: Modulo:Navbox/styles.css e Modulo:Navbox/mobile-styles.css.


--[[
* Modulo per implementare le funzionalità dei template Navbox e Navbox_subgroup.
* Costruisce un template di navigazione basato su una table HTML.
]]

require("Module:No globals")

local getArgs = require("Modulo:Arguments").getArgs

-- Configurazione
local cfg = mw.loadData("Modulo:Navbox/Configurazione")

-------------------------------------------------------------------------------
--                             Funzioni di utilità
-------------------------------------------------------------------------------

-- Ritorna true se il nome dell'argomento è valido
local function isValidArg(name, validArgs, maxList)
	local ret = validArgs[name] ~= nil

	if not ret then
		local id = name:match("^list(%d+)$") or name:match("^group(%d+)$") or
			name:match("^list(%d+)style$") or name:match("^group(%d+)style$")
		if id then
			ret = tonumber(id) <= maxList
		end
	end

	return ret
end

-- Ritorna gli argomenti passati al modulo, scartando quelli senza nome,
-- quelli contenenti stringhe vuote e i non riconosciuti.
local function parseArgs(args, isSubgroup)
	local ret = {}
	local validArgs = isSubgroup and cfg.subgroupArgs or cfg.navboxArgs
	local maxList = isSubgroup and cfg.subgroupMaxList or cfg.navboxMaxList

	for k, v in pairs(args) do
		if type(k) == "string" and v ~= "" and isValidArg(k, validArgs, maxList) then
			ret[k] = v
		end
	end

	return ret
end

-- Ritorna gli ID degli argomenti listN presenti
local function getListIds(args)
	local ret = {}

	for k, v in pairs(args) do
		local id = k:match("^list(%d+)$")
		if id then
			table.insert(ret, tonumber(id))
		end
	end
	table.sort(ret)

	return ret
end

-- Con il debug ridefinisce il metodo mw.html:css,
-- permettendo di eseguire i test senza controllare anche i css.
local function disableCSS(tableNode)
   local mt = getmetatable(tableNode)
   mt.__index.css = function(t, name, val) return t end
end

-------------------------------------------------------------------------------
--                           classe Navbox
-------------------------------------------------------------------------------

local Navbox = {}

function Navbox:new(args)
	local self = {}
	local thNode
	local thStyle = {
		["text-align"] = "center",
		width = "100%",
		background = "#ccf",
		["font-size"] = "90%"
	}

	setmetatable(self, { __index = Navbox,
						 __tostring = function(t) return self:__tostring() end })
	self.args = args
	-- costruzione table
	self.tableNode = mw.html.create("table")
	if self.args.debug then
		disableCSS(self.tableNode)
	end
	self:__setupTableNode()
	-- prima row: contiene la navbar e il titolo
	thNode = self.tableNode:tag("tr")
		:tag("th")
			:attr("colspan", self.args.image and "3" or "2")
			:css(thStyle)
			:cssText(self.args.titlestyle)
	if self.args.navbar ~= "plain" then
		self:__addTnavbar(thNode)
	end
	if self.args.title then
		self:__addTitle(thNode)
	end
	-- eventuale row per l'above
	if self.args.above then
		self:__addAboveOrBelow(self.args.above, self.args.abovestyle)
	end
	-- altre row
	self:__addLists()
	-- eventuale row finale per il below
	if self.args.below then
		self:__addAboveOrBelow(self.args.below, self.args.belowstyle)
	end

	return self
end

function Navbox:__tostring()
	return tostring(self.tableNode)
end

function Navbox:__setupTableNode()
	local tableStyle = {
		margin = "auto",
		width = "100%",
		clear = "both",
		border = "1px solid #aaa",
		padding = "2px"
	}
	self.tableNode
		:addClass("navbox")
		:addClass("mw-collapsible")
		:addClass(self.args.state == "collapsed" and "mw-collapsed" or
				  (self.args.state == "autocollapse" and "autocollapse" or
				  (not self.args.state and "autocollapse" or nil)))
		:addClass("nowraplinks")
		:addClass("noprint")
		:addClass("metadata")
		:css(tableStyle)
		:cssText(self.args.style)
		:cssText(self.args.bodystyle)
end

function Navbox:__addTnavbar(node)
	local divStyle = {
		float = "left",
		width = "6em",
		["text-align"] = "left",
		padding = "0 10px 0 0",
		margin = "0px"
	}
	local tnavbar = mw.getCurrentFrame():expandTemplate {
		title = "Tnavbar",
		args = {
			[1] = self.args.name,
			["mini"] = 1
		}
	}
	node:tag("div"):css(divStyle):wikitext(tnavbar)
end

function Navbox:__addTitle(node)
	node:tag("span"):css("font-size", "110%"):wikitext(self.args.title)
end

function Navbox:__addAboveOrBelow(arg, argStyle)
	local tdStyle = {
		background = "#ddf",
		["text-align"] = "center",
		["font-size"] = "90%"
	}
	self.tableNode
		:tag("tr")
			:tag("td")
				:attr("colspan", self.args.image and "3" or "2")
				:css(tdStyle)
				:cssText(argStyle)
				:wikitext(arg)
end

function Navbox:__addImage(trNode, rowspan)
	local tdStyle = {
		["vertical-align"] = "middle",
		["padding-left"] = "7px",
		width = "0%"
	}
	trNode
		:tag("td")
			:attr("rowspan", rowspan)
			:css(tdStyle)
			:cssText(self.args.imagestyle)
			:wikitext(self.args.image)
end

function Navbox:__addLists()
	local listIds, altStyle, altBackground
	local thStyle = {
		background = "#ddf",
		["white-space"] = "nowrap",
		padding = "0 10px",
		["font-size"] = "90%"
	}
	-- crea una row per ogni listN
	listIds = getListIds(self.args)
	for _, id in ipairs(listIds) do
		local trNode = self.tableNode:tag("tr")
		-- i groupN sono visibili solo se c'è la corrispettiva listN
		if self.args["group" .. id] then
			trNode:tag("th")
				:css(thStyle)
				:cssText(self.args.groupstyle)
				:cssText(self.args["group" .. id .. "style"])
				:wikitext(self.args["group" .. id])
		end
		if (id % 2) == 0 then
			altStyle = self.args.evenstyle
			altBackground = "#f7f7f7"
		else
			altStyle = self.args.oddstyle
			altBackground = nil
		end
		trNode:tag("td")
			:attr("colspan", self.args["group" .. id] and "1" or "2")
			:css("width", "100%")
			:css("font-size", "90%")
			:css("text-align", self.args["group" .. id] and "left" or "center")
			:css("background", altBackground)
			:cssText(self.args.liststyle)
			:cssText(altStyle)
			:cssText(self.args["list" .. id .. "style"])
			:wikitext(self.args["list" .. id])
		if id == 1 and self.args.image then
			self:__addImage(trNode, #listIds)
		end
	end
end

-------------------------------------------------------------------------------
--                           classe NavboxSubgroup
-------------------------------------------------------------------------------

local NavboxSubgroup = {}

function NavboxSubgroup:new(args)
	local self = {}

	setmetatable(self, { __index = NavboxSubgroup,
						 __tostring = function(t) return self:__tostring() end })
	self.args = args
	-- costruzione table
	self.tableNode = mw.html.create("table")
	if self.args.debug then
		disableCSS(self.tableNode)
	end
	self:__setupTableNode()
	self:__addLists()

	return self
end

function NavboxSubgroup:__tostring()
	return tostring(self.tableNode)
end

function NavboxSubgroup:__setupTableNode()
	local tableStyle = {
		background = "transparent",
		["font-size"] = "100%",
		padding = "0",
		border = "0",
		margin = "-3px",
		width = "100%"
	}
	self.tableNode
		:addClass("navbox")
		:addClass("nowraplinks")
		:css(tableStyle)
		:cssText(self.args.bodystyle)
end

function NavboxSubgroup:__addLists()
	local listIds, altStyle
	local thStyle = {
		background = "#ddf",
		padding = "0 10px",
	}
	-- crea una row per ogni listN
	listIds = getListIds(self.args)
	for _, id in ipairs(listIds) do
		local trNode = self.tableNode:tag("tr")
		-- i groupN sono visibili solo se c'è la corrispettiva listN
		if self.args["group" .. id] then
			trNode:tag("th")
				:css(thStyle)
				:cssText(self.args.groupstyle)
				:wikitext(self.args["group" .. id])
		end
		if (id % 2) == 0 then
			altStyle = self.args.evenstyle
		else
			altStyle = self.args.oddstyle
		end
		trNode:tag("td")
			:attr("colspan", self.args["group" .. id] and "1" or "2")
			:css("text-align", self.args["group" .. id] and "left" or "center")
			:cssText(self.args.liststyle)
			:cssText(altStyle)
			:wikitext(self.args["list" .. id])
	end
end

-------------------------------------------------------------------------------
--                                    API
-------------------------------------------------------------------------------

local p = {}

function p._navbox(args)
	return Navbox:new(parseArgs(args))
end

function p._navbox_subgroup(args)
	return NavboxSubgroup:new(parseArgs(args, true))
end

-- Entry-point per {{Navbox}}
function p.navbox(frame)
	return p._navbox(getArgs(frame, {wrappers = 'Template:Navbox'}))
end

-- Entry-point per {{Navbox subgroup}}
function p.navbox_subgroup(frame)
	return p._navbox_subgroup(getArgs(frame, {wrappers = 'Template:Navbox subgroup'}))
end

return p