Module:Navbox timeline: Difference between revisions

Trying out months change (AI)
Tag: Reverted
No edit summary
Tag: Reverted
Line 5: Line 5:
local getArgs = require('Module:Arguments').getArgs
local getArgs = require('Module:Arguments').getArgs
local p = {}
local p = {}
-- Convert date string to fractional year for timeline positioning
local function parseDate(dateStr)
if not dateStr then return nil end
-- Handle year-month format (YYYY-MM or YYYY/MM)
local year, month = dateStr:match('^(%d%d%d%d)[%-/](%d%d?)$')
if year and month then
year = tonumber(year)
month = tonumber(month)
if month < 1 or month > 12 then
error('Invalid month: ' .. month .. ' (must be 1-12)', 0)
end
-- Convert to fractional year (e.g., 2020.5 for June 2020)
return year + (month - 1) / 12
end
-- Handle year only
local yearOnly = dateStr:match('^(%d%d%d%d)$')
if yearOnly then
return tonumber(yearOnly)
end
return nil
end


-- Add blank table cells
-- Add blank table cells
Line 15: Line 40:
while date < current do
while date < current do
local dur = math.min(1, current - date) -- 1 month duration
local dur = math.min(1/12, current - date) -- 1 month duration in fractional years
local colspanMonths = math.max(1, math.round(dur * 12))
row:tag('td')
row:tag('td')
:addClass('timeline-blank')
:addClass('timeline-blank')
:cssText(args.blankstyle)
:cssText(args.blankstyle)
:attr('colspan', dur)
:attr('colspan', colspanMonths)
date = date + dur
date = date + dur
end
end
else
else
local yearDiff = current - prev
row:tag('td')
row:tag('td')
:addClass('timeline-blank')
:addClass('timeline-blank')
:cssText(args.blankstyle)
:cssText(args.blankstyle)
:attr('colspan', current - prev)
:attr('colspan', math.max(1, math.round(yearDiff)))
end
end
else
else
-- Divide the cell up every decade if showing decades at the top
-- Divide the cell up every decade if showing decades at the top
local year = prev
local year = math.floor(prev)
local endYear = math.ceil(current)
while year < current do
while year < endYear do
local dur = math.min(10 - year % 10, current - year)
local dur = math.min(10 - year % 10, endYear - year)
row:tag('td')
row:tag('td')
Line 84: Line 112:
then
then
local dates = mw.text.split(fullVal, '-', true)
local dates = mw.text.split(fullVal, '-', true)
local startYear = tonumber(dates[1])
local startYear = parseDate(dates[1])
local endYear = tonumber(dates[2]) or tonumber(os.date('%Y')) + 1
local endYear = parseDate(dates[2]) or (tonumber(os.date('%Y')) + 1)
if startYear == nil then
if startYear == nil then
Line 111: Line 139:
end
end
-- Add overrides from arguments
-- Add overrides from arguments (handle fractional years)
if args.startoffset then
if args.startoffset then
rows.minYear = rows.minYear - tonumber(args.startoffset)
rows.minYear = rows.minYear - tonumber(args.startoffset)
end
end
if args.startyear and tonumber(args.startyear) < rows.minYear then
if args.startyear then
rows.minYear = tonumber(args.startyear)
local startOverride = parseDate(args.startyear) or tonumber(args.startyear)
if startOverride and startOverride < rows.minYear then
rows.minYear = startOverride
end
end
end
Line 124: Line 155:
end
end
if args.endyear and tonumber(args.endyear) > rows.maxYear then
if args.endyear then
rows.maxYear = tonumber(args.endyear)
local endOverride = parseDate(args.endyear) or tonumber(args.endyear)
if endOverride and endOverride > rows.maxYear then
rows.maxYear = endOverride
end
end
end


Line 168: Line 202:
local decadeRow = tbl:tag('tr')
local decadeRow = tbl:tag('tr')
:addClass('timeline-row')
:addClass('timeline-row')
local year = rows.minYear
local year = math.floor(rows.minYear)
local maxYear = math.ceil(rows.maxYear)
-- Move decade row  
-- Move decade row  
Line 175: Line 210:
end
end
while year < rows.maxYear do
while year < maxYear do
local dur = math.min(10 - year % 10, rows.maxYear - year)
local dur = math.min(10 - year % 10, maxYear - year)
decadeRow:tag('th')
decadeRow:tag('th')
Line 199: Line 234:
-- Calculate total months in range
-- Calculate total months in range
local totalMonths = (rows.maxYear - rows.minYear) * 12
local totalMonths = math.ceil((rows.maxYear - rows.minYear) * 12)
local monthWidth = 100 / totalMonths
local monthWidth = 100 / totalMonths
for year = rows.minYear, rows.maxYear - 1 do
local currentDate = rows.minYear
for month = 1, 12 do
while currentDate < rows.maxYear do
monthRow:tag('th')
local year = math.floor(currentDate)
:attr('scope', 'col')
local month = math.floor((currentDate - year) * 12) + 1
:addClass('timeline-month')
:cssText(args.datestyle)
monthRow:tag('th')
:cssText(args.monthstyle)
:attr('scope', 'col')
:cssText('width:' .. monthWidth .. '%')
:addClass('timeline-month')
:wikitext(getMonthAbbr(month))
:cssText(args.datestyle)
end
:cssText(args.monthstyle)
:cssText('width:' .. monthWidth .. '%')
:wikitext(getMonthAbbr(month))
currentDate = currentDate + 1/12
end
end
end
end
Line 218: Line 257:
if showDecades == false and showMonths ~= false then
if showDecades == false and showMonths ~= false then
-- When showing months, each year spans 12 columns
-- When showing months, each year spans 12 columns
for year = rows.minYear, rows.maxYear - 1 do
local year = math.floor(rows.minYear)
local maxYear = math.ceil(rows.maxYear)
for currentYear = year, maxYear - 1 do
yearRow:tag('th')
yearRow:tag('th')
:attr('scope', 'col')
:attr('scope', 'col')
Line 225: Line 267:
:cssText(args.yearstyle)
:cssText(args.yearstyle)
:attr('colspan', '12')
:attr('colspan', '12')
:wikitext(tostring(year))
:wikitext(tostring(currentYear))
end
end
else
else
-- Normal year display
-- Normal year display
local width = 100 / (rows.maxYear - rows.minYear)
local yearSpan = rows.maxYear - rows.minYear
local width = 100 / yearSpan
for i = rows.minYear, rows.maxYear - 1 do
local year = math.floor(rows.minYear)
local maxYear = math.ceil(rows.maxYear)
for i = year, maxYear - 1 do
yearRow:tag('th')
yearRow:tag('th')
:attr('scope', 'col')
:attr('scope', 'col')
Line 276: Line 322:
-- Shrink previous item so new item can start at the start year
-- Shrink previous item so new item can start at the start year
if prevItem and prev > prevEndYear then
if prevItem and prev > prevEndYear then
local colspan = prevItem:getAttr('colspan')
local colspan = tonumber(prevItem:getAttr('colspan')) or 1
local adjustment = prev - prevEndYear
if yesno(args.decades) == false and yesno(args.months) ~= false then
if yesno(args.decades) == false and yesno(args.months) ~= false then
-- Adjust for months
-- Adjust for months
prevItem:attr('colspan', colspan - (prev - prevEndYear) * 12)
adjustment = math.round(adjustment * 12)
else
else
prevItem:attr('colspan', colspan - prev + prevEndYear)
adjustment = math.round(adjustment)
end
end
prevItem:attr('colspan', math.max(1, colspan - adjustment))
end
end


Line 294: Line 344:
local colspan = cell.endYear - cell.startYear
local colspan = cell.endYear - cell.startYear
if yesno(args.decades) == false and yesno(args.months) ~= false then
if yesno(args.decades) == false and yesno(args.months) ~= false then
-- Each year represents 12 months
-- Each month is one column
colspan = colspan * 12
colspan = math.max(1, math.round(colspan * 12))
else
colspan = math.max(1, math.round(colspan))
end
end
Line 314: Line 366:
-- Remove any extra rowspan from the label
-- Remove any extra rowspan from the label
if prevLabel and labelSpan > 0 then
if prevLabel and labelSpan > 0 then
prevLabel:attr('rowspan', prevLabel:getAttr('rowspan') - labelSpan);
prevLabel:attr('rowspan', (tonumber(prevLabel:getAttr('rowspan')) or 1) - labelSpan);
end
end
end
end