Differenze tra le versioni di "Modulo:Navbox"

Da Destiny One.
(non è efficiente iterare su tutta la table per ogni parametro listN/groupN del modulo, fix ripetizione funzione getListIds/getIds)
(navigation div instead of single-cell table wrapper)
Riga 1: Riga 1:
--[[
+
--
* Modulo per implementare le funzionalità dei template Navbox e Navbox_subgroup.
+
-- This module implements {{Navbox}}
* Costruisce un template di navigazione basato su una table HTML.
+
--
]]
 
  
require('Modulo:No globals')
+
local p = {}
  
local getArgs = require('Modulo:Arguments').getArgs
+
local navbar = require('Module:Navbar')._navbar
 +
local getArgs -- lazily initialized
  
-- Configurazione
+
local args
local cfg = mw.loadData('Modulo:Navbox/Configurazione')
+
local tableRowAdded = false
 +
local border
 +
local listnums = {}
  
-------------------------------------------------------------------------------
+
local function trim(s)
--                            Funzioni di utilità
+
    return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1"))
-------------------------------------------------------------------------------
+
end
  
-- Ritorna true se il nome dell'argomento è valido
+
local function addNewline(s)
local function isValidArg(name, validArgs, maxList)
+
    if s:match('^[*:;#]') or s:match('^{|') then
local ret = validArgs[name] ~= nil
+
        return '\n' .. s ..'\n'
 +
    else
 +
        return s
 +
    end
 +
end
  
if not ret then
+
local function addTableRow(tbl)
local id = name:match('^list(%d+)$') or name:match('^group(%d+)$') or
+
    -- If any other rows have already been added, then we add a 2px gutter row.
name:match('^list(%d+)style$') or name:match('^group(%d+)style$')
+
    if tableRowAdded then
if id then
+
        tbl
ret = tonumber(id) <= maxList
+
            :tag('tr')
end
+
                :css('height', '2px')
end
+
                :tag('td')
 +
                    :attr('colspan',2)
 +
    end
  
return ret
+
    tableRowAdded = true
 +
 
 +
    return tbl:tag('tr')
 
end
 
end
  
-- Ritorna gli argomenti passati al modulo, scartando quelli senza nome,
+
local function renderNavBar(titleCell)
-- quelli contenenti stringhe vuote e i non riconosciuti.
+
    -- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left
local function parseArgs(args, isSubgroup)
+
    -- or right to keep the title centered.
local ret = {}
+
    local spacerSide = nil
local validArgs = isSubgroup and cfg.subgroupArgs or cfg.navboxArgs
+
 
local maxList = isSubgroup and cfg.subgroupMaxList or cfg.navboxMaxList
+
    if args.navbar == 'off' then
 +
        -- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's
 +
        -- also no show/hide link, then we need a spacer on the right to achieve the left shift.
 +
        if args.state == 'plain' then spacerSide = 'right' end
 +
    elseif args.navbar == 'plain' or (not args.name and mw.getCurrentFrame():getParent():getTitle():gsub('/sandbox$', '') == 'Template:Navbox') then
 +
        -- No navbar. Need a spacer on the left to balance out the width of the show/hide link.
 +
        if args.state ~= 'plain' then spacerSide = 'left' end
 +
    else
 +
        -- Will render navbar (or error message). If there's no show/hide link, need a spacer on the right
 +
        -- to balance out the width of the navbar.
 +
        if args.state == 'plain' then spacerSide = 'right' end
  
for k, v in pairs(args) do
+
        titleCell:wikitext(navbar{
if type(k) == 'string' and v ~= '' and isValidArg(k, validArgs, maxList) then
+
            args.name,
ret[k] = v
+
            mini = 1,
end
+
            fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') ..  ';background:none transparent;border:none;'
end
+
        })
 +
    end
  
return ret
+
    -- Render the spacer div.
 +
    if spacerSide then
 +
        titleCell
 +
            :tag('span')
 +
                :css('float', spacerSide)
 +
                :css('width', '6em')
 +
                :wikitext('&nbsp;')
 +
    end
 
end
 
end
  
-- Ritorna una sequence contenente gli ID dei listN presenti, ordinata e senza duplicati.
+
--
-- Se withGroup è true, controlla anche i groupN.
+
--   Title row
local function getIds(args, withGroup)
+
--
local ids = {}
+
local function renderTitleRow(tbl)
local ret = {}
+
    if not args.title then return end
+
 
-- siccome Lua ha solo le table e non i set (elementi unici), prima popola ids usando le chiavi
+
    local titleRow = addTableRow(tbl)
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
+
    if args.titlegroup then
for k, _ in pairs(ids) do
+
        titleRow
table.insert(ret, k)
+
            :tag('th')
end
+
                :attr('scope', 'row')
table.sort(ret)
+
                :addClass('navbox-group')
 +
                :addClass(args.titlegroupclass)
 +
                :cssText(args.basestyle)
 +
                :cssText(args.groupstyle)
 +
                :cssText(args.titlegroupstyle)
 +
                :wikitext(args.titlegroup)
 +
    end
  
return ret
+
    local titleCell = titleRow:tag('th'):attr('scope', 'col')
 +
 
 +
    if args.titlegroup then
 +
        titleCell
 +
            :css('border-left', '2px solid #fdfdfd')
 +
            :css('width', '100%')
 +
    end
 +
 
 +
    local titleColspan = 2
 +
    if args.imageleft then titleColspan = titleColspan + 1 end
 +
    if args.image then titleColspan = titleColspan + 1 end
 +
    if args.titlegroup then titleColspan = titleColspan - 1 end
 +
 
 +
    titleCell
 +
        :cssText(args.basestyle)
 +
        :cssText(args.titlestyle)
 +
        :addClass('navbox-title')
 +
        :attr('colspan', titleColspan)
 +
 
 +
    renderNavBar(titleCell)
 +
 
 +
    titleCell
 +
        :tag('div')
 +
            :attr('id', mw.uri.anchorEncode(args.title))
 +
            :addClass(args.titleclass)
 +
            :css('font-size', '114%')
 +
            :wikitext(addNewline(args.title))
 
end
 
end
  
-- Toglie eventuali spazi/a capo dannosi attorno ai {{,}}
+
--
local function trimSep(list)
+
--  Above/Below rows
local sep = mw.getCurrentFrame():expandTemplate{title=","}
+
--
local sepEsc = mw.ustring.gsub(sep, '-', '%-')
+
 
return mw.ustring.gsub(list, '%s*' .. sepEsc .. '%s*', sep)
+
local function getAboveBelowColspan()
 +
    local ret = 2
 +
    if args.imageleft then ret = ret + 1 end
 +
    if args.image then ret = ret + 1 end
 +
    return ret
 
end
 
end
  
-- Con il debug ridefinisce il metodo mw.html:css,
+
local function renderAboveRow(tbl)
-- permettendo di eseguire i test senza controllare anche i css.
+
    if not args.above then return end
local function disableCSS(tableNode)
+
 
local mt = getmetatable(tableNode)
+
    addTableRow(tbl)
mt.__index.css = function(t, name, val) return t end
+
        :tag('td')
 +
            :addClass('navbox-abovebelow')
 +
            :addClass(args.aboveclass)
 +
            :cssText(args.basestyle)
 +
            :cssText(args.abovestyle)
 +
            :attr('colspan', getAboveBelowColspan())
 +
            :tag('div')
 +
                :wikitext(addNewline(args.above))
 
end
 
end
  
-------------------------------------------------------------------------------
+
local function renderBelowRow(tbl)
--                          classe Navbox
+
    if not args.below then return end
-------------------------------------------------------------------------------
 
  
local Navbox = {}
+
    addTableRow(tbl)
 +
        :tag('td')
 +
            :addClass('navbox-abovebelow')
 +
            :addClass(args.belowclass)
 +
            :cssText(args.basestyle)
 +
            :cssText(args.belowstyle)
 +
            :attr('colspan', getAboveBelowColspan())
 +
            :tag('div')
 +
                :wikitext(addNewline(args.below))
 +
end
  
function Navbox:new(args)
+
--
local self = {}
+
--  List rows
local thNode
+
--
local thStyle = {
+
local function renderListRow(tbl, listnum)
['text-align'] = 'center',
+
    local row = addTableRow(tbl)
width = '100%',
 
background = '#ccf',
 
['font-size'] = '90%'
 
}
 
  
setmetatable(self, { __index = Navbox })
+
    if listnum == 1 and args.imageleft then
self.args = args
+
        row
-- costruzione table
+
            :tag('td')
self.tableNode = mw.html.create('table')
+
                :addClass('navbox-image')
if self.args.debug then
+
                :addClass(args.imageclass)
disableCSS(self.tableNode)
+
                :css('width', '0%')
end
+
                :css('padding', '0px 2px 0px 0px')
self:_setupTableNode()
+
                :cssText(args.imageleftstyle)
-- prima row: contiene la navbar e il titolo
+
                :attr('rowspan', 2 * #listnums - 1)
thNode = self.tableNode:tag('tr')
+
                :tag('div')
:tag('th')
+
                    :wikitext(addNewline(args.imageleft))
:attr('colspan', self.args.image and '3' or '2')
+
    end
: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
+
    if args['group' .. listnum] then
 +
        local groupCell = row:tag('th')
 +
 
 +
        groupCell
 +
            :attr('scope', 'row')
 +
            :addClass('navbox-group')
 +
            :addClass(args.groupclass)
 +
            :cssText(args.basestyle)
 +
 
 +
        if args.groupwidth then
 +
            groupCell:css('width', args.groupwidth)
 +
        end
 +
 
 +
        groupCell
 +
            :cssText(args.groupstyle)
 +
            :cssText(args['group' .. listnum .. 'style'])
 +
            :wikitext(args['group' .. listnum])
 +
    end
 +
 
 +
    local listCell = row:tag('td')
 +
 
 +
    if args['group' .. listnum] then
 +
        listCell
 +
            :css('text-align', 'left')
 +
            :css('border-left-width', '2px')
 +
            :css('border-left-style', 'solid')
 +
    else
 +
        listCell:attr('colspan', 2)
 +
    end
 +
 
 +
    if not args.groupwidth then
 +
        listCell:css('width', '100%')
 +
    end
 +
 
 +
    local isOdd = (listnum % 2) == 1
 +
    local rowstyle = args.evenstyle
 +
    if isOdd then rowstyle = args.oddstyle end
 +
 
 +
    local evenOdd
 +
    if args.evenodd == 'swap' then
 +
        if isOdd then evenOdd = 'even' else evenOdd = 'odd' end
 +
    else
 +
        if isOdd then evenOdd = args.evenodd or 'odd' else evenOdd = args.evenodd or 'even' end
 +
    end
 +
 
 +
    listCell
 +
        :css('padding', '0px')
 +
        :cssText(args.liststyle)
 +
        :cssText(rowstyle)
 +
        :cssText(args['list' .. listnum .. 'style'])
 +
        :addClass('navbox-list')
 +
        :addClass('navbox-' .. evenOdd)
 +
        :addClass(args.listclass)
 +
        :tag('div')
 +
            :css('padding', (listnum == 1 and args.list1padding) or args.listpadding or '0em 0.25em')
 +
            :wikitext(addNewline(args['list' .. listnum]))
 +
 
 +
    if listnum == 1 and args.image then
 +
        row
 +
            :tag('td')
 +
                :addClass('navbox-image')
 +
                :addClass(args.imageclass)
 +
                :css('width', '0%')
 +
                :css('padding', '0px 0px 0px 2px')
 +
                :cssText(args.imagestyle)
 +
                :attr('rowspan', 2 * #listnums - 1)
 +
                :tag('div')
 +
                    :wikitext(addNewline(args.image))
 +
    end
 
end
 
end
  
function Navbox:getHTML()
+
 
return tostring(self.tableNode)
+
--
 +
--  Tracking categories
 +
--
 +
 
 +
local function needsHorizontalLists()
 +
    if border == 'child' or border == 'subgroup'  or args.tracking == 'no' then return false end
 +
 
 +
    local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent'}
 +
    for i, cls in ipairs(listClasses) do
 +
        if args.listclass == cls or args.bodyclass == cls then
 +
            return false
 +
        end
 +
    end
 +
 
 +
    return true
 
end
 
end
  
function Navbox:_setupTableNode()
+
local function hasBackgroundColors()
local tableStyle = {
+
    return mw.ustring.match(args.titlestyle or '','background') or mw.ustring.match(args.groupstyle or '','background') or mw.ustring.match(args.basestyle or '','background')
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
 
end
  
function Navbox:_addTnavbar(node)
+
local function isIllegible()
local divStyle = {
+
    local styleratio = require('Module:Color contrast')._styleratio
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)
+
    for key, style in pairs(args) do
node:tag('span'):css('font-size', '110%'):wikitext(self.args.title)
+
        if tostring(key):match("style$") then
 +
            if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then
 +
                return true
 +
            end
 +
        end
 +
    end
 +
    return false
 
end
 
end
  
function Navbox:_addAboveOrBelow(arg, argStyle)
+
local function getTrackingCategories()
local tdStyle = {
+
    local cats = {}
background = '#ddf',
+
    if needsHorizontalLists() then table.insert(cats, 'Navigational boxes without horizontal lists') end
['text-align'] = 'center',
+
    if hasBackgroundColors() then table.insert(cats, 'Navboxes using background colours') end
['font-size'] = '90%'
+
    if isIllegible() then table.insert(cats, 'Potentially illegible navboxes') end
}
+
    return cats
self.tableNode
 
:tag('tr')
 
:tag('td')
 
:attr('colspan', self.args.image and '3' or '2')
 
:css(tdStyle)
 
:cssText(argStyle)
 
:wikitext(arg)
 
 
end
 
end
  
function Navbox:_addImage(trNode, rowspan)
+
local function renderTrackingCategories(builder)
local tdStyle = {
+
    local title = mw.title.getCurrentTitle()
['vertical-align'] = 'middle',
+
    if title.namespace ~= 10 then return end -- not in template space
['padding-left'] = '7px',
+
    local subpage = title.subpageText
width = '0%'
+
    if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end
}
 
trNode
 
:tag('td')
 
:attr('rowspan', rowspan)
 
:css(tdStyle)
 
:cssText(self.args.imagestyle)
 
:wikitext(self.args.image)
 
end
 
  
function Navbox:_addLists()
+
    for i, cat in ipairs(getTrackingCategories()) do
local rowIds, altStyle, altBackground
+
        builder:wikitext('[[Category:' .. cat .. ']]')
local thStyle = {
+
    end
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
 
end
  
-------------------------------------------------------------------------------
+
--
--                          classe NavboxSubgroup
+
--   Main navbox tables
-------------------------------------------------------------------------------
+
--
 +
local function renderMainTable()
 +
    local tbl = mw.html.create('table')
 +
        :addClass('nowraplinks')
 +
        :addClass(args.bodyclass)
  
local NavboxSubgroup = {}
+
    if args.title and (args.state ~= 'plain' and args.state ~= 'off') then
 +
        tbl
 +
            :addClass('collapsible')
 +
            :addClass(args.state or 'autocollapse')
 +
    end
  
function NavboxSubgroup:new(args)
+
    tbl:css('border-spacing', 0)
local self = {}
+
    if border == 'subgroup' or border == 'child' or border == 'none' then
 +
        tbl
 +
            :addClass('navbox-subgroup')
 +
            :cssText(args.bodystyle)
 +
            :cssText(args.style)
 +
    else -- regular navobx - bodystyle and style will be applied to the wrapper table
 +
        tbl
 +
            :addClass('navbox-inner')
 +
            :css('background', 'transparent')
 +
            :css('color', 'inherit')
 +
    end
 +
    tbl:cssText(args.innerstyle)
  
setmetatable(self, { __index = NavboxSubgroup })
+
    renderTitleRow(tbl)
self.args = args
+
    renderAboveRow(tbl)
-- costruzione table
+
    for i, listnum in ipairs(listnums) do
self.tableNode = mw.html.create('table')
+
        renderListRow(tbl, listnum)
if self.args.debug then
+
    end
disableCSS(self.tableNode)
+
    renderBelowRow(tbl)
end
 
self:_setupTableNode()
 
self:_addLists()
 
  
return self
+
    return tbl
 
end
 
end
  
function NavboxSubgroup:getHTML()
+
function p._navbox(navboxArgs)
return tostring(self.tableNode)
+
    args = navboxArgs
end
 
  
function NavboxSubgroup:_setupTableNode()
+
    for k, v in pairs(args) do
local tableStyle = {
+
        local listnum = ('' .. k):match('^list(%d+)$')
background = 'transparent',
+
        if listnum then table.insert(listnums, tonumber(listnum)) end
['font-size'] = '100%',
+
    end
padding = '0',
+
    table.sort(listnums)
border = '0',
 
margin = '-3px',
 
width = '100%'
 
}
 
self.tableNode
 
:addClass('navbox')
 
:addClass('nowraplinks')
 
:css(tableStyle)
 
:cssText(self.args.bodystyle)
 
end
 
  
function NavboxSubgroup:_addLists()
+
    border = trim(args.border or args[1] or '')
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
 
  
-------------------------------------------------------------------------------
+
    -- render the main body of the navbox
--                                    API
+
    local tbl = renderMainTable()
-------------------------------------------------------------------------------
 
  
local p = {}
+
    -- render the appropriate wrapper around the navbox, depending on the border param
 +
    local res = mw.html.create()
 +
    if border == 'none' then
 +
        local nav = res:tag('div')
 +
            :attr('role', 'navigation')
 +
            :node(tbl)
 +
        if args.title then
 +
            nav:attr('aria-labelledby', mw.uri.anchorEncode(args.title))
 +
        else
 +
            nav:attr('aria-label', 'Navbox')
 +
        end
 +
    elseif border == 'subgroup' or border == 'child' then
 +
        -- We assume that this navbox is being rendered in a list cell of a parent navbox, and is
 +
        -- therefore inside a div with padding:0em 0.25em. We start with a </div> to avoid the
 +
        -- padding being applied, and at the end add a <div> to balance out the parent's </div>
 +
        res
 +
            :wikitext('</div>') -- XXX: hack due to lack of unclosed support in mw.html.
 +
            :node(tbl)
 +
            :wikitext('<div>') -- XXX: hack due to lack of unclosed support in mw.html.
 +
    else
 +
        local nav = res:tag('div')
 +
            :attr('role', 'navigation')
 +
            :addClass('navbox')
 +
            :cssText(args.bodystyle)
 +
            :cssText(args.style)
 +
            :css('padding', '3px')
 +
            :node(tbl)
 +
        if args.title then
 +
            nav:attr('aria-labelledby', mw.uri.anchorEncode(args.title))
 +
        else
 +
            nav:attr('aria-label', 'Navbox')
 +
        end
 +
    end
  
function p._navbox(args)
+
    renderTrackingCategories(res)
return Navbox:new(parseArgs(args)):getHTML()
 
end
 
  
function p._navbox_subgroup(args)
+
    return tostring(res)
return NavboxSubgroup:new(parseArgs(args, true)):getHTML()
 
 
end
 
end
  
-- Entry-point per {{Navbox}}
 
 
function p.navbox(frame)
 
function p.navbox(frame)
return p._navbox(getArgs(frame, {wrappers = 'Template:Navbox'}))
+
    if not getArgs then
end
+
        getArgs = require('Module:Arguments').getArgs
 +
    end
 +
    args = getArgs(frame, {wrappers = 'Template:Navbox'})
 +
 
 +
    -- Read the arguments in the order they'll be output in, to make references number in the right order.
 +
    local _
 +
    _ = args.title
 +
    _ = args.above
 +
    for i = 1, 20 do
 +
        _ = args["group" .. tostring(i)]
 +
        _ = args["list" .. tostring(i)]
 +
    end
 +
    _ = args.below
  
-- Entry-point per {{Navbox subgroup}}
+
    return p._navbox(args)
function p.navbox_subgroup(frame)
 
return p._navbox_subgroup(getArgs(frame, {wrappers = 'Template:Navbox subgroup'}))
 
 
end
 
end
  
 
return p
 
return p

Versione delle 04:34, 16 lug 2016

La documentazione per questo modulo può essere creata in Modulo:Navbox/man

--
-- This module implements {{Navbox}}
--

local p = {}

local navbar = require('Module:Navbar')._navbar
local getArgs -- lazily initialized

local args
local tableRowAdded = false
local border
local listnums = {}

local function trim(s)
    return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1"))
end

local function addNewline(s)
    if s:match('^[*:;#]') or s:match('^{|') then
        return '\n' .. s ..'\n'
    else
        return s
    end
end

local function addTableRow(tbl)
    -- If any other rows have already been added, then we add a 2px gutter row.
    if tableRowAdded then
        tbl
            :tag('tr')
                :css('height', '2px')
                :tag('td')
                    :attr('colspan',2)
    end

    tableRowAdded = true

    return tbl:tag('tr')
end

local function renderNavBar(titleCell)
    -- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left
    -- or right to keep the title centered.
    local spacerSide = nil

    if args.navbar == 'off' then
        -- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's
        -- also no show/hide link, then we need a spacer on the right to achieve the left shift.
        if args.state == 'plain' then spacerSide = 'right' end
    elseif args.navbar == 'plain' or (not args.name and mw.getCurrentFrame():getParent():getTitle():gsub('/sandbox$', '') == 'Template:Navbox') then
        -- No navbar. Need a spacer on the left to balance out the width of the show/hide link.
        if args.state ~= 'plain' then spacerSide = 'left' end
    else
        -- Will render navbar (or error message). If there's no show/hide link, need a spacer on the right
        -- to balance out the width of the navbar.
        if args.state == 'plain' then spacerSide = 'right' end

        titleCell:wikitext(navbar{
            args.name,
            mini = 1,
            fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') ..  ';background:none transparent;border:none;'
        })
    end

    -- Render the spacer div.
    if spacerSide then
        titleCell
            :tag('span')
                :css('float', spacerSide)
                :css('width', '6em')
                :wikitext('&nbsp;')
    end
end

--
--   Title row
--
local function renderTitleRow(tbl)
    if not args.title then return end

    local titleRow = addTableRow(tbl)

    if args.titlegroup then
        titleRow
            :tag('th')
                :attr('scope', 'row')
                :addClass('navbox-group')
                :addClass(args.titlegroupclass)
                :cssText(args.basestyle)
                :cssText(args.groupstyle)
                :cssText(args.titlegroupstyle)
                :wikitext(args.titlegroup)
    end

    local titleCell = titleRow:tag('th'):attr('scope', 'col')

    if args.titlegroup then
        titleCell
            :css('border-left', '2px solid #fdfdfd')
            :css('width', '100%')
    end

    local titleColspan = 2
    if args.imageleft then titleColspan = titleColspan + 1 end
    if args.image then titleColspan = titleColspan + 1 end
    if args.titlegroup then titleColspan = titleColspan - 1 end

    titleCell
        :cssText(args.basestyle)
        :cssText(args.titlestyle)
        :addClass('navbox-title')
        :attr('colspan', titleColspan)

    renderNavBar(titleCell)

    titleCell
        :tag('div')
            :attr('id', mw.uri.anchorEncode(args.title))
            :addClass(args.titleclass)
            :css('font-size', '114%')
            :wikitext(addNewline(args.title))
end

--
--   Above/Below rows
--

local function getAboveBelowColspan()
    local ret = 2
    if args.imageleft then ret = ret + 1 end
    if args.image then ret = ret + 1 end
    return ret
end

local function renderAboveRow(tbl)
    if not args.above then return end

    addTableRow(tbl)
        :tag('td')
            :addClass('navbox-abovebelow')
            :addClass(args.aboveclass)
            :cssText(args.basestyle)
            :cssText(args.abovestyle)
            :attr('colspan', getAboveBelowColspan())
            :tag('div')
                :wikitext(addNewline(args.above))
end

local function renderBelowRow(tbl)
    if not args.below then return end

    addTableRow(tbl)
        :tag('td')
            :addClass('navbox-abovebelow')
            :addClass(args.belowclass)
            :cssText(args.basestyle)
            :cssText(args.belowstyle)
            :attr('colspan', getAboveBelowColspan())
            :tag('div')
                :wikitext(addNewline(args.below))
end

--
--   List rows
--
local function renderListRow(tbl, listnum)
    local row = addTableRow(tbl)

    if listnum == 1 and args.imageleft then
        row
            :tag('td')
                :addClass('navbox-image')
                :addClass(args.imageclass)
                :css('width', '0%')
                :css('padding', '0px 2px 0px 0px')
                :cssText(args.imageleftstyle)
                :attr('rowspan', 2 * #listnums - 1)
                :tag('div')
                    :wikitext(addNewline(args.imageleft))
    end

    if args['group' .. listnum] then
        local groupCell = row:tag('th')

        groupCell
            :attr('scope', 'row')
            :addClass('navbox-group')
            :addClass(args.groupclass)
            :cssText(args.basestyle)

        if args.groupwidth then
            groupCell:css('width', args.groupwidth)
        end

        groupCell
            :cssText(args.groupstyle)
            :cssText(args['group' .. listnum .. 'style'])
            :wikitext(args['group' .. listnum])
    end

    local listCell = row:tag('td')

    if args['group' .. listnum] then
        listCell
            :css('text-align', 'left')
            :css('border-left-width', '2px')
            :css('border-left-style', 'solid')
    else
        listCell:attr('colspan', 2)
    end

    if not args.groupwidth then
        listCell:css('width', '100%')
    end

    local isOdd = (listnum % 2) == 1
    local rowstyle = args.evenstyle
    if isOdd then rowstyle = args.oddstyle end

    local evenOdd
    if args.evenodd == 'swap' then
        if isOdd then evenOdd = 'even' else evenOdd = 'odd' end
    else
        if isOdd then evenOdd = args.evenodd or 'odd' else evenOdd = args.evenodd or 'even' end
    end

    listCell
        :css('padding', '0px')
        :cssText(args.liststyle)
        :cssText(rowstyle)
        :cssText(args['list' .. listnum .. 'style'])
        :addClass('navbox-list')
        :addClass('navbox-' .. evenOdd)
        :addClass(args.listclass)
        :tag('div')
            :css('padding', (listnum == 1 and args.list1padding) or args.listpadding or '0em 0.25em')
            :wikitext(addNewline(args['list' .. listnum]))

    if listnum == 1 and args.image then
        row
            :tag('td')
                :addClass('navbox-image')
                :addClass(args.imageclass)
                :css('width', '0%')
                :css('padding', '0px 0px 0px 2px')
                :cssText(args.imagestyle)
                :attr('rowspan', 2 * #listnums - 1)
                :tag('div')
                    :wikitext(addNewline(args.image))
    end
end


--
--   Tracking categories
--

local function needsHorizontalLists()
    if border == 'child' or border == 'subgroup'  or args.tracking == 'no' then return false end

    local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent'}
    for i, cls in ipairs(listClasses) do
        if args.listclass == cls or args.bodyclass == cls then
            return false
        end
    end

    return true
end

local function hasBackgroundColors()
    return mw.ustring.match(args.titlestyle or '','background') or mw.ustring.match(args.groupstyle or '','background') or mw.ustring.match(args.basestyle or '','background')
end

local function isIllegible()
    local styleratio = require('Module:Color contrast')._styleratio

    for key, style in pairs(args) do
        if tostring(key):match("style$") then
            if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then
                return true 
            end
        end
    end
    return false
end

local function getTrackingCategories()
    local cats = {}
    if needsHorizontalLists() then table.insert(cats, 'Navigational boxes without horizontal lists') end
    if hasBackgroundColors() then table.insert(cats, 'Navboxes using background colours') end
    if isIllegible() then table.insert(cats, 'Potentially illegible navboxes') end
    return cats
end

local function renderTrackingCategories(builder)
    local title = mw.title.getCurrentTitle()
    if title.namespace ~= 10 then return end -- not in template space
    local subpage = title.subpageText
    if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end

    for i, cat in ipairs(getTrackingCategories()) do
        builder:wikitext('[[Category:' .. cat .. ']]')
    end
end

--
--   Main navbox tables
--
local function renderMainTable()
    local tbl = mw.html.create('table')
        :addClass('nowraplinks')
        :addClass(args.bodyclass)

    if args.title and (args.state ~= 'plain' and args.state ~= 'off') then
        tbl
            :addClass('collapsible')
            :addClass(args.state or 'autocollapse')
    end

    tbl:css('border-spacing', 0)
    if border == 'subgroup' or border == 'child' or border == 'none' then
        tbl
            :addClass('navbox-subgroup')
            :cssText(args.bodystyle)
            :cssText(args.style)
    else -- regular navobx - bodystyle and style will be applied to the wrapper table
        tbl
            :addClass('navbox-inner')
            :css('background', 'transparent')
            :css('color', 'inherit')
    end
    tbl:cssText(args.innerstyle)

    renderTitleRow(tbl)
    renderAboveRow(tbl)
    for i, listnum in ipairs(listnums) do
        renderListRow(tbl, listnum)
    end
    renderBelowRow(tbl)

    return tbl
end

function p._navbox(navboxArgs)
    args = navboxArgs

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

    border = trim(args.border or args[1] or '')

    -- render the main body of the navbox
    local tbl = renderMainTable()

    -- render the appropriate wrapper around the navbox, depending on the border param
    local res = mw.html.create()
    if border == 'none' then
        local nav = res:tag('div')
            :attr('role', 'navigation')
            :node(tbl)
        if args.title then
            nav:attr('aria-labelledby', mw.uri.anchorEncode(args.title))
        else
            nav:attr('aria-label', 'Navbox')
        end
    elseif border == 'subgroup' or border == 'child' then
        -- We assume that this navbox is being rendered in a list cell of a parent navbox, and is
        -- therefore inside a div with padding:0em 0.25em. We start with a </div> to avoid the
        -- padding being applied, and at the end add a <div> to balance out the parent's </div>
        res
            :wikitext('</div>') -- XXX: hack due to lack of unclosed support in mw.html.
            :node(tbl)
            :wikitext('<div>') -- XXX: hack due to lack of unclosed support in mw.html.
    else
        local nav = res:tag('div')
            :attr('role', 'navigation')
            :addClass('navbox')
            :cssText(args.bodystyle)
            :cssText(args.style)
            :css('padding', '3px')
            :node(tbl)
        if args.title then
            nav:attr('aria-labelledby', mw.uri.anchorEncode(args.title))
        else
            nav:attr('aria-label', 'Navbox')
        end
    end

    renderTrackingCategories(res)

    return tostring(res)
end

function p.navbox(frame)
    if not getArgs then
        getArgs = require('Module:Arguments').getArgs
    end
    args = getArgs(frame, {wrappers = 'Template:Navbox'})

    -- Read the arguments in the order they'll be output in, to make references number in the right order.
    local _
    _ = args.title
    _ = args.above
    for i = 1, 20 do
        _ = args["group" .. tostring(i)]
        _ = args["list" .. tostring(i)]
    end
    _ = args.below

    return p._navbox(args)
end

return p