Module:Navbox

Ord Wikipedia
Midar tar: navigaziun, tschertga

Documentation for this module may be created at Module:Navbox/doc

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

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

-------------------------------------------------------------------------------
--                             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 getArgs(frame, 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(frame:getParent().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("collapsible")
        :addClass(self.args.state == "collapsed" and "collapsed" or
                  (self.args.state == "autocollapse" and "autocollapse" or
                  (not self.args.state and "autocollapse" or nil)))
        :addClass("nowraplinks")
        :addClass("noprint")
        :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 = {}

-- Entry-point per {{Navbox}}
function p.navbox(frame)
    return Navbox:new(getArgs(frame))
end

-- Entry-point per {{Navbox subgroup}}
function p.navbox_subgroup(frame)
    return NavboxSubgroup:new(getArgs(frame, true))
end

return p