Module:Navbox timeline/sandbox explained

require('strict')

local yesno = require('Module:Yesno')local navbox = require('Module:Navbox')._navboxlocal getArgs = require('Module:Arguments').getArgslocal p =

-- Add blank table cellslocal function addBlank(args, row, prev, current) if row and prev < current then if yesno(args.decades)

false then row:tag('td') :addClass('timeline-blank') :cssText(args.blankstyle) :attr('colspan', current - prev) else -- Divide the cell up every decade if showing decades at the top local year = prev while year < current do local dur = math.min(10 - year % 10, current - year) row:tag('td') :addClass('timeline-blank') :cssText(args.blankstyle) :attr('colspan', dur) year = year + dur end end endend

-- Get timeline datalocal function timelineInfo(args) local rows = for num, fullVal in ipairs(args) do local key, val = fullVal:match('^([a-z]+): *(.*)$') local cellIndex = #rows[#rows] -- Row data key value pairs if cellIndex

0 and key then rows[#rows][key] = val -- Record that there are labels if key

'label' then rows.hasLabels = true end -- Data cell key value pairs elseif key then -- Data cell key value pairs rows[#rows][cellIndex][key] = val -- New row elseif fullVal

then if next(rows[#rows]) then table.insert(rows,) end -- Add date to cell with item already and no date elseif cellIndex > 0 and rows[#rows][cellIndex].item and not rows[#rows][cellIndex].startYear then local dates = mw.text.split(fullVal, '-', true) local startYear = tonumber(dates[1]) local endYear = tonumber(dates[2]) or tonumber(os.date('%Y')) + 1 if startYear

nil then error('Argument ' .. num .. ' is an invalid time range', 0) end if endYear < startYear then error('Argument ' .. num .. '\'s end year is less than the start year', 0) end

rows[#rows][cellIndex].startYear = startYear rows[#rows][cellIndex].endYear = endYear

if startYear < rows.minYear then rows.minYear = startYear end

if endYear > rows.maxYear then rows.maxYear = endYear end -- New item else table.insert(rows[#rows],) end end -- Add overrides from arguments if args.startoffset then rows.minYear = rows.minYear - tonumber(args.startoffset) end if args.startyear and tonumber(args.startyear) < rows.minYear then rows.minYear = tonumber(args.startyear) end if args.endoffset then rows.maxYear = rows.maxYear + tonumber(args.endoffset) end if args.endyear and tonumber(args.endyear) > rows.maxYear then rows.maxYear = tonumber(args.endyear) end

return rowsend

-- Render the date rowslocal function renderDates(args, tbl, rows, invert) local showDecades = yesno(args.decades) local yearRow = tbl:tag('tr') :addClass('timeline-row') -- Create label if args.label or rows.hasLabels then local labelCell = mw.html.create('th') :attr('scope', 'col') :addClass('navbox-group timeline-label') :cssText(args.labelstyle) :attr('rowspan', showDecades ~= false and '2' or '1') :wikitext(args.label or ) yearRow:node(labelCell) end

-- Create decade row if showDecades ~= false then local decadeRow = tbl:tag('tr') :addClass('timeline-row') local year = rows.minYear -- Move decade row if not invert then decadeRow, yearRow = yearRow, decadeRow end while year < rows.maxYear do local dur = math.min(10 - year % 10, rows.maxYear - year) decadeRow:tag('th') :attr('scope', 'col') :addClass('timeline-decade') :cssText(args.datestyle) :cssText(args.decadestyle) :attr('colspan', dur) :wikitext(math.floor(year / 10) .. '0s') year = year + dur end end -- Populate year row element local width = 100 / (rows.maxYear - rows.minYear) for i = rows.minYear, rows.maxYear - 1 do yearRow:tag('th') :attr('scope', 'col') :addClass('timeline-year') :cssText(args.datestyle) :cssText(args.yearstyle) :cssText('width:' .. width .. '%') :wikitext(showDecades

false and i or i % 10) endend

-- Render the timeline itselflocal function renderTimeline(args, tbl, rows) local rowElement = nil local rowSuffix = nil local prev = rows.minYear local prevItem = nil local prevLabel = nil local labelSpan = 0 for rowNum, row in ipairs(rows) do local rowElement = tbl:tag('tr') :addClass('timeline-row') if labelSpan <= 0 and (rows.hasLabels or args.label) then labelSpan = tonumber(row.span) or 1 prevLabel = rowElement:tag('th') :attr('scope', 'row') :attr('rowspan', labelSpan) :addClass('navbox-group timeline-label') :cssText(args.labelstyle) :cssText(row.labelstyle) :wikitext(row.label) end labelSpan = labelSpan - 1 local prevEndYear = rows.minYear local prevItem = nil for cellNum, cell in ipairs(row) do -- Shrink previous item so new item can start at the start year if prevItem and prev > prevEndYear then prevItem:attr('colspan', prevItem:getAttr('colspan') - prev + prevEndYear); end

if cell.startYear

nil then error('Missing timerange for row ' .. rowNum .. ' cell ' .. cellNum, 0) end -- Add blanks before the cell addBlank(args, rowElement, prevEndYear, cell.startYear) prevItem = rowElement:tag('td') :addClass('timeline-item') :cssText(args.itemstyle) :cssText(cell.style or ) :attr('colspan', cell.endYear - cell.startYear) :wikitext(cell.item)

prevEndYear = cell.endYear end -- Add blanks to the end of the row addBlank(args, rowElement, prevEndYear, rows.maxYear) end -- Remove any extra rowspan from the label if prevLabel and labelSpan > 0 then prevLabel:attr('rowspan', prevLabel:getAttr('rowspan') - labelSpan); endend

function p.main(frame) local args = getArgs(frame,) local targs = -- Arguments to passthrough to navbox local passthrough = local rows = timelineInfo(args) local wrapper = mw.html.create('table') :addClass('timeline-wrapper') local tbl = wrapper:tag('tr') :tag('td') :addClass('timeline-wrapper-cell') :tag('table') :addClass('timeline-table') renderDates(args, tbl, rows) renderTimeline(args, tbl, rows) if yesno(args.footer) then renderDates(args, tbl, rows, true) end for _, name in ipairs(passthrough) do targs[name] = args[name] end

targs.templatestyles = 'Module:Navbox timeline/styles.css' targs.list1 = tostring(wrapper) return navbox(targs)end

return p