Module:Navbox with collapsible groups
Documentation for this module may be created at Module:Navbox with collapsible groups/doc
-- This module implements {{Navbox with collapsible groups}} require('strict') local p = {} local parentCfg = mw.loadData('Module:Navbox/configuration') local thisCfg = mw.loadData('Module:Navbox with collapsible groups/configuration') local cfg = {} for k, v in pairs(thisCfg) do if type(v) == 'table' then cfg[k] = {} if type(parentCfg[k]) == 'table' then for kk, vv in pairs(parentCfg[k]) do cfg[k][kk] = vv end end for kk, vv in pairs(v) do cfg[k][kk] = vv end end end local inArray = require("Module:TableTools").inArray local getArgs -- lazily initialized -- helper functions local andnum = function(s, n) return string.format(cfg.arg[s..'_and_num'], n) end local isblank = function(v) return (v or '') == '' end local function concatstrings(s) local r = table.concat(s, '') if r:match('^%s*$') then return nil end return r end local function concatstyles(s) local r = '' for _, v in ipairs(s) do v = mw.text.trim(v, "%s;") if not isblank(v) then r = r .. v .. ';' end end if isblank(r) then return nil end return r end local function getSubgroup(args, listnum, listText) local subArgs = { [cfg.arg.border] = cfg.keyword.border_subgroup, [cfg.arg.navbar] = cfg.keyword.navbar_plain } local hasSubArgs = false for k, v in pairs(args) do k = tostring(k) for _, w in ipairs(cfg.keyword.subgroups) do w = w .. listnum .. "_" if (#k > #w) and (k:sub(1, #w) == w) then subArgs[k:sub(#w + 1)] = v hasSubArgs = true end end end return hasSubArgs and p._navbox(subArgs) or listText end -- Main functions p._navbox = require('Module:Navbox')._navbox function p._withCollapsibleGroups(pargs) -- table for args passed to navbox local targs = {} -- process args local passthrough = { [cfg.arg.above]=true,[cfg.arg.aboveclass]=true,[cfg.arg.abovestyle]=true, [cfg.arg.basestyle]=true, [cfg.arg.below]=true,[cfg.arg.belowclass]=true,[cfg.arg.belowstyle]=true, [cfg.arg.bodyclass]=true,[cfg.arg.bodystyle]=true, [cfg.arg.border]=true, [cfg.arg.groupclass]=true, [cfg.arg.image]=true,[cfg.arg.imageclass]=true,[cfg.arg.imagestyle]=true, [cfg.arg.imageleft]=true,[cfg.arg.imageleftstyle]=true, [cfg.arg.listclass]=true, [cfg.arg.name]=true, [cfg.arg.navbar]=true, [cfg.arg.state]=true, [cfg.arg.style]=true, [cfg.arg.title]=true,[cfg.arg.titleclass]=true,[cfg.arg.titlestyle]=true } for k,v in pairs(pargs) do if k and type(k) == 'string' then if passthrough[k] then targs[k] = v elseif (k:match(cfg.pattern.num)) then local n = k:match(cfg.pattern.num) local list_and_num = andnum('list', n) if ((k:match(cfg.pattern.listnum) or k:match(cfg.pattern.contentnum)) and targs[list_and_num] == nil and pargs[andnum('group', n)] == nil and pargs[andnum('sect', n)] == nil and pargs[andnum('section', n)] == nil) then targs[list_and_num] = concatstrings({ pargs[list_and_num] or '', pargs[andnum('content', n)] or '' }) if (targs[list_and_num] and inArray(cfg.keyword.subgroups, targs[list_and_num])) then targs[list_and_num] = getSubgroup(pargs, n, targs[list_and_num]) end elseif ((k:match(cfg.pattern.groupnum) or k:match(cfg.pattern.sectnum) or k:match(cfg.pattern.sectionnum)) and targs[list_and_num] == nil) then local titlestyle = concatstyles({ pargs[cfg.arg.groupstyle] or '', pargs[cfg.arg.secttitlestyle] or '', pargs[andnum('groupstyle', n)] or '', pargs[andnum('sectiontitlestyle', n)] or '' }) local liststyle = concatstyles({ pargs[cfg.arg.liststyle] or '', pargs[cfg.arg.contentstyle] or '', pargs[andnum('liststyle', n)] or '', pargs[andnum('contentstyle', n)] or '' }) local title = concatstrings({ pargs[andnum('group', n)] or '', pargs[andnum('sect', n)] or '', pargs[andnum('section', n)] or '' }) local list = concatstrings({ pargs[list_and_num] or '', pargs[andnum('content', n)] or '' }) if list and inArray(cfg.keyword.subgroups, list) then list = getSubgroup(pargs, n, list) end local abbr_and_num = andnum('abbr', n) local state = (pargs[abbr_and_num] and pargs[abbr_and_num] == pargs[cfg.arg.selected]) and cfg.keyword.state_uncollapsed or (pargs[andnum('state', n)] or cfg.keyword.state_collapsed) targs[list_and_num] =p._navbox({ cfg.keyword.border_child, [cfg.arg.navbar] = cfg.keyword.navbar_plain, [cfg.arg.state] = state, [cfg.arg.basestyle] = pargs[cfg.arg.basestyle], [cfg.arg.title] = title, [cfg.arg.titlestyle] = titlestyle, [andnum('list', 1)] = list, [cfg.arg.liststyle] = liststyle, [cfg.arg.listclass] = pargs[andnum('listclass', n)], [cfg.arg.image] = pargs[andnum('image', n)], [cfg.arg.imageleft] = pargs[andnum('imageleft', n)], [cfg.arg.listpadding] = pargs[cfg.arg.listpadding] }) end end end end -- ordering of style and bodystyle targs[cfg.arg.style] = concatstyles({targs[cfg.arg.style] or '', targs[cfg.arg.bodystyle] or ''}) targs[cfg.arg.bodystyle] = nil -- child or subgroup if targs[cfg.arg.border] == nil then targs[cfg.arg.border] = pargs[1] end return p._navbox(targs) end -- Template entry points function p.navbox (frame, boxtype) local function readArgs(args, prefix) -- Read the arguments in the order they'll be output in, to make references -- number in the right order. local _ _ = args[prefix .. cfg.arg.title] _ = args[prefix .. cfg.arg.above] -- Limit this to 20 as covering 'most' cases (that's a SWAG) and because -- iterator approach won't work here for i = 1, 20 do _ = args[prefix .. andnum('group', i)] if inArray(cfg.keyword.subgroups, args[prefix .. andnum('list', i)]) then for _, v in ipairs(cfg.keyword.subgroups) do readArgs(args, prefix .. v .. i .. "_") end end end _ = args[prefix .. cfg.arg.below] end if not getArgs then getArgs = require('Module:Arguments').getArgs end local args = getArgs(frame, {wrappers = {cfg.pattern[boxtype or 'navbox']}}) readArgs(args, "") return p['_'..(boxtype or 'navbox')](args) end p['with collapsible groups'] = function (frame) return p.navbox(frame, 'withCollapsibleGroups') end local q = {} q._navbox = p._withCollapsibleGroups q.navbox = p['with collapsible groups'] return q