Modulo:Navbox
La documentazione per questo modulo può essere creata in Modulo:Navbox/man
--[[
* Modulo per implementare le funzionalità dei template Navbox e Navbox_subgroup.
* Costruisce un template di navigazione basato su una table HTML.
]]
require('Modulo: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 una sequence contenente gli ID dei listN presenti, ordinata e senza duplicati.
-- Se withGroup è true, controlla anche i groupN.
local function getIds(args, withGroup)
local ids = {}
local ret = {}
-- siccome Lua ha solo le table e non i set (elementi unici), prima popola ids usando le chiavi
for k, _ in pairs(args) do
local id = k:match('^list(%d+)$') or (withGroup and k:match('^group(%d+)$'))
if id then
ids[tonumber(id)] = 1
end
end
-- quindi ritorna una sequence fatta delle chiavi della table ids
for k, _ in pairs(ids) do
table.insert(ret, k)
end
table.sort(ret)
return ret
end
-- Toglie eventuali spazi/a capo dannosi attorno ai {{,}}
local function trimSep(list)
local sep = mw.getCurrentFrame():expandTemplate{title=","}
local sepEsc = mw.ustring.gsub(sep, '-', '%-')
return mw.ustring.gsub(list, '%s*' .. sepEsc .. '%s*', sep)
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 })
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:getHTML()
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 rowIds, altStyle, altBackground
local thStyle = {
background = '#ddf',
['white-space'] = 'nowrap',
padding = '0 10px',
['font-size'] = '90%'
}
-- crea una riga per ogni groupN/listN
rowIds = getIds(self.args, true)
for _, id in ipairs(rowIds) do
local trNode = self.tableNode:tag('tr')
-- groupN
if self.args['group' .. id] then
trNode:tag('th')
:attr('colspan', self.args['list' .. id] and '1' or '2')
:css(thStyle)
:cssText(self.args.groupstyle)
:cssText(self.args['group' .. id .. 'style'])
:wikitext(self.args['group' .. id])
end
-- listN
if self.args['list' .. id] then
local list = trimSep(self.args['list' .. id])
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(list)
end
if id == 1 and self.args.image then
self:_addImage(trNode, #rowIds)
end
end
end
-------------------------------------------------------------------------------
-- classe NavboxSubgroup
-------------------------------------------------------------------------------
local NavboxSubgroup = {}
function NavboxSubgroup:new(args)
local self = {}
setmetatable(self, { __index = NavboxSubgroup })
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:getHTML()
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 = getIds(self.args)
for _, id in ipairs(listIds) do
local trNode = self.tableNode:tag('tr')
local list = trimSep(self.args['list' .. id])
-- 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(list)
end
end
-------------------------------------------------------------------------------
-- API
-------------------------------------------------------------------------------
local p = {}
function p._navbox(args)
return Navbox:new(parseArgs(args)):getHTML()
end
function p._navbox_subgroup(args)
return NavboxSubgroup:new(parseArgs(args, true)):getHTML()
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