Jump to content

Module:Ahnentafel

Permanently protected module
From Wikipedia, the free encyclopedia

--
-- implements [[Template:ahnentafel]]
--
local p = {}
-- templatestyles
local templatestyles = 'Ahnentafel/styles.css'
-- table of row pointers
local rows = {}
-- first and last indices in rows table
local rowbegin, rowend = -1,-1
-- tracking
local tcats = ''

local function checkparameters(k)
	if (k == 'align' or k == 'collapsed' or k == 'collapsible' or
		k == 'title' or k == 'float' or k == 'clear' or k == 'ref' or
		k == 'headnotes' or k == 'headnotes_align' or 
		k == 'footnotes' or k == 'footnotes_align' or k == 'rtl' or
		k == 'width' or k == 'min-width' or k == 'text-align') then
		return
	elseif (k == 'boxstyle' or k == 'style' or k == 'border') then
		tcats = tcats .. '[[Category:Pages using ahnentafel with ' .. k .. ']]'
		return
	elseif k:find('^boxstyle_[1-8]$') then
		return
	elseif k:find('^border_[1-8]$') then
		return
	end
	k = mw.ustring.gsub(k, '[^%w%-_ ]', '?')
	tcats = tcats .. '[[Category:Pages using ahnentafel with unknown parameters|' .. k .. ' ]]'
end

local function addcell(r, rspan, cspan, t, s, c)
	if ((r + rspan - 1) < rowbegin) or (r > rowend) then
		-- completely out of range; do nothing
		return
	elseif r < rowbegin then
		-- partially out of range, adjust
		rspan = rspan - (rowbegin - r)
		r = rowbegin
	elseif (r + rspan - 1) > rowend then
		-- partially out of range, adjust
		rspan = rowend + 1 - r
	end
	if rspan > 0 then
		rows[r]:tag('td')
			:attr('rowspan', (rspan > 1) and rspan or nil)
			:attr('colspan', (cspan > 1) and cspan or nil)
			:cssText(s)
			:addClass(c)
			:wikitext(t)
	end
end

function p.chart( frame )
	local getArgs = require('Module:Arguments').getArgs
	local args = getArgs(frame)
	local align = (args['align'] or ''):lower()
	local style = args['style'] or ''
	local topbranch = 'ahnentafel-t'
	local botbranch = 'ahnentafel-b'

	local yesno = require('Module:Yesno')
	
	if args['collapsed'] and args['collapsed'] ~= '' then
		args['collapsible'] = 'yes'
	end
	
	if args['title'] and args['title'] ~= '' then
		args['collapsible'] = 'yes'
		if yesno(args['collapsed'] or 'no') then
			args['collapsed'] = 'yes'
		else
			args['collapsed'] = 'no'
		end
	end
	
	-- 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 and track unsupported parameters
	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
		elseif (k and type(k) == 'string') then
			checkparameters(k)
		end
	end

	-- limit the number of levels
	maxnum = (maxnum > 511) and 511 or maxnum
	
	local levels = math.ceil(math.log(maxnum+1)/math.log(2))
	local cells  = math.pow(2, levels) - 1
	
	-- "fill in" missing boxes
	for k = cells, 2, -1 do
		local j = math.floor(k/2)
		if args[k] and args[k] ~= '' and
		   (args[j] == nil or args[j] == '') then
				args[j] = ' ' -- single space
		end
	end
	
	-- compute the first and last row number
	rowbegin = 2*cells+1
	rowend   = 2*cells+2
	local cellnum = 0
	for l = 1,levels do
		local cellsk = math.pow(2,l-1)
		local offset = 1
		for k = 1,cellsk do
			cellnum = cellnum + 1
			offset = offset + 2 * (math.pow(2, levels-l + 1) - 1)
			if args[cellnum] and args[cellnum] ~= '' then
				rowbegin = (offset < rowbegin) and offset or rowbegin
				rowend = ((offset+1) > rowend) and (offset+1) or rowend
			end
			if args[cellnum] and args[cellnum] == '' then
				args[cellnum] = nil
			end
			offset = offset + 2*(math.pow(2,levels-l+1)-1) + 4
		end
	end
	
	-- add a collapsing outer container if required
	local res = mw.html.create('')
	local innercell = res
	local innerfs = '88%'
	if yesno(args['collapsible'] or 'no') then
		local r = res:tag('table')
		local t = args['title'] or ('Ancestors of ' .. mw.title.getCurrentTitle().text)
		r:addClass('collapsible')
		if yesno(args['collapsed'] or 'yes') then
			r:addClass('collapsed')
		end
		local f = args['float'] or ''
		if f == 'left' then
			r:css('margin', '0.3em 1em 0.3em 0')
			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 0 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')
		elseif  align == 'center' then
			r:css('margin', '0.3em auto')
			r:css('clear', args['clear'] or 'none')
			r:css('min-width', args['min-width'] or args['width'] or '60em')
		else
			r:css('margin', '0.3em 0')
			r:css('min-width', args['min-width'] or args['width'] or '60em')
		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('color', 'inherit')
				:css('width', args['width'] or 'auto')
				:wikitext(t .. (args['ref'] or ''))
		innercell = r:tag('tr'):tag('td')
				:css('text-align', args['text-align'] or 'center')
		innerfs = nil
		args['ref'] = nil
	end

	-- add content before the table if required
	if args['headnotes'] then
		if args['headnotes_align'] then
			innercell:tag('div')
				:css('width','100%')
				:css('text-align',args['headnotes_align'])
				:wikitext(args['headnotes'])
		else
			innercell:wikitext(args['headnotes'])
		end
	end

	-- build the inner table
	local root = innercell:tag('table')
	root:addClass('ahnentafel')
		:css('font-size', innerfs)
		:cssText(style)

	-- initialize the rows with 1 by 1 blank cells
	for k = rowbegin, (rowend+1) do
		rows[k] = root:tag('tr')
		rows[k]:tag('td'):wikitext(' ')
	end
	-- add a blank row of cells to assist with alignment
	for k = 1,(3*levels + 1) do
		rows[rowend+1]: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 = 'height:0.5em; padding:0 0.2em;' .. levelstyle
		levelstyle = 'border:' .. (args['border_' .. l] or args['border'] or '1') .. 'px solid black;' .. levelstyle
		
		local cellsk = math.pow(2,l-1)
		local offset = 1
		for k = 1,cellsk do
			cellnum = cellnum + 1
			-- top padding
			addcell(offset, 2*(math.pow(2,levels-l+1)-1), (l < levels) and 2 or 4, ' ', nil, nil)
			-- top branch
			if l < levels then
				addcell(offset, math.pow(2,levels-l+1)-1, 1, ' ', nil, nil)
				addcell(offset + math.pow(2,levels-l+1)-1, math.pow(2,levels-l+1)-1, 1, ' ', nil,
					args[2*cellnum] and topbranch or nil)
			end
			offset = offset + 2*(math.pow(2,levels-l+1)-1)
			-- cell
			addcell(offset, 2, 4, args[cellnum] or ' ', args[cellnum] and levelstyle or nil, nil)
			if l < levels then
				addcell(offset, 2, 3 + 4*(levels - l - 1), ' ', nil, nil)
			end
			offset = offset + 2
			-- bottom padding
			addcell(offset, 2*(math.pow(2,levels-l+1)-1), (l < levels) and 2 or 4, ' ', nil, nil)
			-- bottom branch
			if l < levels then
				addcell(offset, math.pow(2,levels-l+1)-1, 1, ' ', nil,
					args[2*cellnum+1] and botbranch or nil)
				addcell(offset + math.pow(2,levels-l+1)-1, math.pow(2,levels-l+1)-1, 1, ' ', nil, nil)
			end
			offset = offset + 2*(math.pow(2,levels-l+1)-1) + 2
		end
	end
	
	-- add content after the table if required
	if args['footnotes'] or args['ref'] then
		if args['footnotes_align'] then
			innercell:tag('div')
				:css('width','100%')
				:css('text-align',args['footnotes_align'])
				:wikitext(args['footnotes'])
		else
			innercell:wikitext(args['ref'])
			innercell:wikitext(args['footnotes'])
		end
	end
	
	return frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles} } 
		.. '<div class="noresize">' .. tostring(res) .. '</div>' .. tcats
end

return p
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy