--
-- implements [[Template:ahnentafel]]
--
local p = {}
function p.chart( frame )
local args = frame.args[1] and frame.args or frame:getParent().args
local align = (args['align'] or ''):lower()
local style = args['style'] or ''
-- style for floating
if (align == 'right') then
style = 'float:right;' .. style
elseif (align == 'left') then
style = 'float:left;' .. style
elseif (align == 'center') then
style = 'margin-left:auto; margin-right:auto;' .. style
end
-- compute the number of levels
local maxnum = 0
for k, v in pairs( args ) do
if k and type(k) == 'number' or (type(k) == 'string' and (tonumber(k) or 0) > 0) then
if tonumber(k) > maxnum then
maxnum = k
end
end
end
local levels = math.ceil(math.log(maxnum+1)/math.log(2))
local cells = math.pow(2, levels) - 1
-- add a collapsing outer container if required
local res = mw.html.create('')
local innercell = res
if args['collapsed'] or args['title'] then
local r = res:tag('table')
local t = args['title'] or ('Ancestors of ' .. mw.title.getCurrentTitle().text)
r:addClass('collapsible')
if args['collapsed'] and args['collapsed'] == 'no' then
r:addClass('expanded')
else
r:addClass('collapsed')
end
local f = args['float'] or ''
if f == 'left' then
r:css('margin', '0.3em 0 0.3em 1em')
r:css('float', 'left')
r:css('clear', args['clear'] or 'left')
r:css('min-width', args['min-width'] or args['width'] or '33em')
elseif f == 'right' then
r:css('margin', '0.3em 1em 0.3em 1em')
r:css('float', 'right')
r:css('clear', args['clear'] or 'right')
r:css('min-width', args['min-width'] or args['width'] or '33em')
else
r:css('margin', '0.3em auto auto')
r:css('clear', args['clear'] or 'none')
r:css('min-width', args['min-width'] or args['width'] or '70em')
end
r:css('width', args['width'] or 'auto')
r:css('font-size', '88%')
r:css('border', '1px solid #aaa')
r:tag('tr'):tag('th')
:css('padding', '0.2em 0.3em 0.2em 4.3em')
:css('background', 'none')
:css('width', args['width'] or 'auto')
:wikitext(t)
innercell = r:tag('tr'):tag('td')
:css('text-align', args['text-align'] or 'center')
end
-- add content before the table if required
if args['headnotes'] then
innercell:wikitext(args['headnotes'])
end
-- build the inner table
local root = innercell:tag('table')
root:css('border-spacing', '0')
:cssText(style)
local rows = {}
for k = 1,2*(2*cells+1) do
rows[k] = root:tag('tr'):css('text-align', 'center')
rows[k]:tag('td'):wikitext(' ')
end
local cellnum = 0
for l = 1,levels do
local levelstyle = args['boxstyle_' .. l] or ''
if args['boxstyle'] and args['boxstyle'] ~= '' then
levelstyle = args['boxstyle'] .. ';' .. levelstyle
end
levelstyle = 'padding:0 0.2em;' .. levelstyle
levelstyle = 'border:' .. (args['border_' .. l] or args['border'] or '2') .. 'px solid black;' .. levelstyle
local cellsk = math.pow(2,l-1)
local offset = 1
for k = 1,cellsk do
cellnum = cellnum + 1
-- top padding
rows[offset]
:tag('td')
:attr('colspan', (l < levels) and 2 or 4)
:attr('rowspan', 2*(math.pow(2,levels-l+1)-1))
:wikitext(' ')
-- top branch
if l < levels then
rows[offset]
:tag('td')
:attr('rowspan', math.pow(2,levels-l+1)-1)
:wikitext(' ')
rows[offset + math.pow(2,levels-l+1)-1]
:tag('td')
:attr('rowspan', math.pow(2,levels-l+1)-1)
:css('border-top', args[2*cellnum] and '#000 solid 1px')
:css('border-left', args[2*cellnum] and '#000 solid 1px')
:wikitext(' ')
end
offset = offset + 2*(math.pow(2,levels-l+1)-1)
-- cell
rows[offset]
:tag('td')
:attr('colspan',4)
:attr('rowspan',2)
:cssText(args[cellnum] and levelstyle)
:wikitext(args[cellnum] or ' ')
if l < levels then
rows[offset]
:tag('td')
:attr('rowspan', 2)
:attr('colspan', 3)
:wikitext(' ')
end
offset = offset + 2
-- bottom padding
rows[offset]
:tag('td')
:attr('colspan', (l < levels) and 2 or 4)
:attr('rowspan', 2*(math.pow(2,levels-l+1)-1))
:wikitext(' ')
-- bottom branch
if l < levels then
rows[offset]
:tag('td')
:attr('rowspan', math.pow(2,levels-l+1)-1)
:css('border-bottom', args[2*cellnum+1] and '#000 solid 1px')
:css('border-left', args[2*cellnum+1] and '#000 solid 1px')
:wikitext(' ')
rows[offset + math.pow(2,levels-l+1)-1]
:tag('td')
:attr('rowspan', math.pow(2,levels-l+1)-1)
:wikitext(' ')
end
offset = offset + 2*(math.pow(2,levels-l+1)-1)
offset = offset + 2
end
end
-- add content after the table if required
if args['footnotes'] then
innercell:wikitext(args['footnotes'])
end
return tostring(res)
end
return p