Module:Navbox and Module:Navbox/sandbox: Difference between pages
Appearance
(Difference between pages)
Content deleted Content added
Read prefixed title, above, and below |
Integrate {{Navbox with columns}}, add "type=" parameter. |
||
Line 1: | Line 1: | ||
require('strict') |
require('strict') |
||
local p = {} |
local p = {} |
||
local cfg = mw.loadData('Module:Navbox/configuration') |
local cfg = mw.loadData('Module:Navbox/configuration/sandbox') |
||
local inArray = require("Module:TableTools").inArray |
local inArray = require("Module:TableTools").inArray |
||
local getArgs -- lazily initialized |
local getArgs -- lazily initialized |
||
local format = string.format |
|||
-- global passthrough variables |
|||
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.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.title]=true,[cfg.arg.titleclass]=true,[cfg.arg.titlestyle]=true, |
|||
} |
|||
-- 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, prefix) |
|||
local subArgs = { |
|||
[cfg.arg.border] = cfg.keyword.border_subgroup, |
|||
[cfg.arg.navbar] = cfg.keyword.navbar_plain |
|||
} |
|||
local hasSubArgs = false |
|||
local subgroups = prefix and {prefix} or cfg.keyword.subgroups |
|||
for k, v in pairs(args) do |
|||
k = tostring(k) |
|||
for _, w in ipairs(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 |
|||
function p._navbox(args) |
function p._navbox(args) |
||
if args.type == cfg.keyword.with_collapsible_groups then |
|||
return p._withCollapsibleGroups(args) |
|||
elseif args.type == cfg.keyword.with_columns then |
|||
return p._withColumns(args) |
|||
end |
|||
local function striped(wikitext, border) |
local function striped(wikitext, border) |
||
-- Return wikitext with markers replaced for odd/even striping. |
-- Return wikitext with markers replaced for odd/even striping. |
||
Line 59: | Line 121: | ||
local prefix, content = line:match('^([*:;#]+)%s*(.*)') |
local prefix, content = line:match('^([*:;#]+)%s*(.*)') |
||
if prefix and not content:match(cfg.pattern.nowrap) then |
if prefix and not content:match(cfg.pattern.nowrap) then |
||
line = format(cfg.nowrap_item, prefix, content) |
line = string.format(cfg.nowrap_item, prefix, content) |
||
end |
end |
||
table.insert(lines, line) |
table.insert(lines, line) |
||
Line 185: | Line 247: | ||
end |
end |
||
local group_and_num = |
local group_and_num = andnum('group', listnum) |
||
local groupstyle_and_num = |
local groupstyle_and_num = andnum('groupstyle', listnum) |
||
if args[group_and_num] then |
if args[group_and_num] then |
||
local groupCell = row:tag('th') |
local groupCell = row:tag('th') |
||
Line 230: | Line 292: | ||
end |
end |
||
local list_and_num = |
local list_and_num = andnum('list', listnum) |
||
local listText = args[list_and_num] |
local listText = inArray(cfg.keyword.subgroups, args[list_and_num]) |
||
and getSubgroup(args, listnum, args[list_and_num]) or args[list_and_num] |
|||
if inArray(cfg.keyword.subgroups, listText) then |
|||
local childArgs = { |
|||
[cfg.arg.border] = cfg.keyword.border_subgroup, |
|||
[cfg.arg.navbar] = cfg.keyword.navbar_plain |
|||
} |
|||
local hasChildArgs = 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 |
|||
childArgs[k:sub(#w + 1)] = v |
|||
hasChildArgs = true |
|||
end |
|||
end |
|||
end |
|||
listText = hasChildArgs and p._navbox(childArgs) or listText |
|||
end |
|||
local oddEven = cfg.marker.oddeven |
local oddEven = cfg.marker.oddeven |
||
Line 258: | Line 302: | ||
end |
end |
||
local liststyle_and_num = |
local liststyle_and_num = andnum('liststyle', listnum) |
||
local listclass_and_num = |
local listclass_and_num = andnum('listclass', listnum) |
||
listCell |
listCell |
||
:css('padding', '0') |
:css('padding', '0') |
||
Line 445: | Line 489: | ||
-- This is a lambda so that it doesn't need the frame as a parameter |
-- This is a lambda so that it doesn't need the frame as a parameter |
||
local function add_user_styles(templatestyles) |
local function add_user_styles(templatestyles) |
||
if |
if not isblank(templatestyles) then |
||
return frame:extensionTag{ |
return frame:extensionTag{ |
||
name = 'templatestyles', args = { src = templatestyles } |
name = 'templatestyles', args = { src = templatestyles } |
||
Line 567: | Line 611: | ||
end |
end |
||
function p. |
function p._withCollapsibleGroups(pargs) |
||
-- table for args passed to navbox |
|||
local targs = {} |
|||
-- process args |
|||
local passthroughLocal = { |
|||
[cfg.arg.bodystyle] = true, |
|||
[cfg.arg.border] = true, |
|||
[cfg.arg.style] = true, |
|||
} |
|||
for k,v in pairs(pargs) do |
|||
if k and type(k) == 'string' then |
|||
if passthrough[k] or passthroughLocal[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 |
|||
function p._withColumns(pargs) |
|||
-- table for args passed to navbox |
|||
local targs = {} |
|||
-- tables of column numbers |
|||
local colheadernums = {} |
|||
local colnums = {} |
|||
local colfooternums = {} |
|||
-- process args |
|||
local passthroughLocal = { |
|||
[cfg.arg.evenstyle]=true, |
|||
[cfg.arg.groupstyle]=true, |
|||
[cfg.arg.liststyle]=true, |
|||
[cfg.arg.oddstyle]=true, |
|||
[cfg.arg.state]=true, |
|||
} |
|||
for k,v in pairs(pargs) do |
|||
if passthrough[k] or passthroughLocal[k] then |
|||
targs[k] = v |
|||
elseif type(k) == 'string' then |
|||
if k:match(cfg.pattern.listnum) then |
|||
local n = k:match(cfg.pattern.listnum) |
|||
targs[andnum('liststyle', n + 2)] = pargs[andnum('liststyle', n)] |
|||
targs[andnum('group', n + 2)] = pargs[andnum('group', n)] |
|||
targs[andnum('groupstyle', n + 2)] = pargs[andnum('groupstyle', n)] |
|||
if v and inArray(cfg.keyword.subgroups, v) then |
|||
targs[andnum('list', n + 2)] = getSubgroup(pargs, n, v) |
|||
else |
|||
targs[andnum('list', n + 2)] = v |
|||
end |
|||
elseif (k:match(cfg.pattern.colheadernum) and v ~= '') then |
|||
table.insert(colheadernums, k:match(cfg.pattern.colheadernum)) |
|||
elseif (k:match(cfg.pattern.colnum) and v ~= '') then |
|||
table.insert(colnums, k:match(cfg.pattern.colnum)) |
|||
elseif (k:match(cfg.pattern.colfooternum) and v ~= '') then |
|||
table.insert(colfooternums, k:match(cfg.pattern.colfooternum)) |
|||
end |
|||
end |
|||
end |
|||
table.sort(colheadernums) |
|||
table.sort(colnums) |
|||
table.sort(colfooternums) |
|||
-- HTML table for list1 |
|||
local coltable = mw.html.create( 'table' ):attr('class', 'navbox-columns-table') |
|||
local row, col |
|||
local tablestyle = ( (#colheadernums > 0) or (not isblank(pargs[cfg.arg.fullwidth])) ) |
|||
and 'width:100%' |
|||
or 'width:auto; margin-left:auto; margin-right:auto' |
|||
coltable:attr('style', concatstyles({ |
|||
'border-spacing: 0px; text-align:left', |
|||
tablestyle, |
|||
pargs[cfg.arg.coltablestyle] or '' |
|||
})) |
|||
--- Header row --- |
|||
if (#colheadernums > 0) then |
|||
row = coltable:tag('tr') |
|||
for k, n in ipairs(colheadernums) do |
|||
col = row:tag('td'):attr('class', 'navbox-abovebelow') |
|||
col:attr('style', concatstyles({ |
|||
(k > 1) and 'border-left:2px solid #fdfdfd' or '', |
|||
'font-weight:bold', |
|||
pargs[cfg.arg.colheaderstyle] or '', |
|||
pargs[andnum('colheaderstyle', n)] or '' |
|||
})) |
|||
if (k < #colheadernums) and tonumber(pargs[andnum('colheadercolspan', n)]) then |
|||
col:attr('colspan', pargs[andnum('colheadercolspan', n)]) |
|||
end |
|||
col:wikitext(pargs[andnum('colheader', n)]) |
|||
end |
|||
end |
|||
--- Main columns --- |
|||
row = coltable:tag('tr'):attr('style', 'vertical-align:top') |
|||
for k, n in ipairs(colnums) do |
|||
if k == 1 and isblank(pargs[andnum('colheader', 1)]) |
|||
and isblank(pargs[andnum('colfooter', 1)]) |
|||
and isblank(pargs[cfg.arg.fullwidth]) then |
|||
local nopad = inArray( |
|||
{'off', '0', '0em', '0px'}, |
|||
mw.ustring.gsub(pargs[cfg.arg.padding] or '', '[;%%]', '')) |
|||
if not nopad then |
|||
row:tag('td'):wikitext(' ') |
|||
:attr('style', 'width:'..(pargs[cfg.arg.padding] or '5em')..';') |
|||
end |
|||
end |
|||
col = row:tag('td'):attr('class', 'navbox-list') |
|||
col:attr('style', concatstyles({ |
|||
(k > 1) and 'border-left:2px solid #fdfdfd' or '', |
|||
'padding:0px', |
|||
pargs[cfg.arg.colstyle] or '', |
|||
((n%2 == 0) and pargs[cfg.arg.evencolstyle] or pargs[cfg.arg.oddcolstyle]) or '', |
|||
pargs[andnum('colstyle', n)] or '', |
|||
'width:' .. (pargs[andnum('colwidth', n)] or pargs[cfg.arg.colwidth] or '10em') |
|||
})) |
|||
local wt = pargs[andnum('col', n)] |
|||
if wt and inArray(cfg.keyword.subgroups, wt) then |
|||
local prefix = mw.ustring.gsub(cfg.arg.col_and_num,"%%d","") |
|||
wt = getSubgroup(pargs, n, wt, prefix) |
|||
end |
|||
col:tag('div'):newline():wikitext(wt):newline() |
|||
end |
|||
--- Footer row --- |
|||
if (#colfooternums > 0) then |
|||
row = coltable:tag('tr') |
|||
for k, n in ipairs(colfooternums) do |
|||
col = row:tag('td'):attr('class', 'navbox-abovebelow') |
|||
col:attr('style', concatstyles({ |
|||
(k > 1) and 'border-left:2px solid #fdfdfd' or '', |
|||
'font-weight:bold', |
|||
pargs[cfg.arg.colfooterstyle] or '', |
|||
pargs[andnum('colfooterstyle', n)] or '' |
|||
})) |
|||
if (k < #colfooternums) and tonumber(pargs[andnum('colfootercolspan', n)]) then |
|||
col:attr('colspan', pargs[andnum('colfootercolspan', n)]) |
|||
end |
|||
col:wikitext(pargs[andnum('colfooter', n)]) |
|||
end |
|||
end |
|||
-- assign table to list1 |
|||
targs[andnum('list', 1)] = tostring(coltable) |
|||
if isblank(pargs[andnum('colheader', 1)]) |
|||
and isblank(pargs[andnum('col', 1)]) |
|||
and isblank(pargs[andnum('colfooter', 1)]) then |
|||
targs[andnum('list', 1)] = targs[andnum('list', 1)] .. |
|||
'[[' .. cfg.pattern.without_first_col .. ']]' |
|||
end |
|||
-- Other parameters |
|||
targs[cfg.arg.border] = pargs[cfg.arg.border] or pargs[1] |
|||
targs[cfg.arg.evenodd] = (not isblank(pargs[cfg.arg.evenodd])) and pargs[cfg.arg.evenodd] or nil |
|||
targs[cfg.arg.list1padding] = '0px' |
|||
targs[andnum('liststyle', 1)] = 'background:transparent;color:inherit;' |
|||
targs[cfg.arg.style] = concatstyles({pargs[cfg.arg.style], pargs[cfg.arg.bodystyle]}) |
|||
targs[cfg.arg.tracking] = 'no' |
|||
return p._navbox(targs) |
|||
end |
|||
-- Template entry points |
|||
function p.navbox (frame, boxtype) |
|||
local function readArgs(args, prefix) |
local function readArgs(args, prefix) |
||
-- Read the arguments in the order they'll be output in, to make references |
-- Read the arguments in the order they'll be output in, to make references |
||
Line 577: | Line 855: | ||
-- iterator approach won't work here |
-- iterator approach won't work here |
||
for i = 1, 20 do |
for i = 1, 20 do |
||
_ = args[prefix .. |
_ = args[prefix .. andnum('group', i)] |
||
if inArray(cfg.keyword.subgroups, args[prefix .. |
if inArray(cfg.keyword.subgroups, args[prefix .. andnum('list', i)]) then |
||
for _, v in ipairs(cfg.keyword.subgroups) do |
for _, v in ipairs(cfg.keyword.subgroups) do |
||
readArgs(args, prefix .. v .. i .. "_") |
readArgs(args, prefix .. v .. i .. "_") |
||
Line 590: | Line 868: | ||
getArgs = require('Module:Arguments').getArgs |
getArgs = require('Module:Arguments').getArgs |
||
end |
end |
||
local args = getArgs(frame, {wrappers = {cfg.pattern |
local args = getArgs(frame, {wrappers = {cfg.pattern[boxtype or 'navbox']}}) |
||
readArgs(args, "") |
readArgs(args, "") |
||
args.type = args.type or cfg.keyword[boxtype] |
|||
return p._navbox(args) |
|||
return p['_navbox'](args) |
|||
end |
|||
p[cfg.keyword.with_collapsible_groups] = function (frame) |
|||
return p.navbox(frame, 'with_collapsible_groups') |
|||
end |
|||
p[cfg.keyword.with_columns] = function (frame) |
|||
return p.navbox(frame, 'with_columns') |
|||
end |
end |
||