Please remember that WiKirby contains spoilers, which you read at your own risk! See our general disclaimer for details.

Module:Sandbox/Calendar

From WiKirby, your independent source of Kirby knowledge.
Jump to navigationJump to search

Creates a calendar of events that displays the current month. Call it with {{#invoke:sandbox/Calendar|calendar|events=Module:Sandbox/Calendar/events}} to make a graphical calendar with the number of events per day, and {{#invoke:sandbox/Calendar|list|events=Module:Sandbox/Calendar/events}} to list the events. These use Module:Sandbox/Calendar/events to gather the events, the events parameter can be changed.


--[[
	This module is an adaptation of Module:Current_events_calendar from Wikipedia
	
	it's experimental at the moment, so beware!!
--]]

local p = {}

function getDateStuff(argsDate)
	local lang = mw.language.getContentLanguage()
	local firstOfMonth = lang:formatDate('01-m-Y', argsDate)
	
	return {
		argsDate = argsDate,
		year = tonumber(lang:formatDate('Y', argsDate)),
		month = lang:formatDate('F', argsDate),
		monthAndYear = lang:formatDate('F Y', argsDate),
		monthNumber = lang:formatDate('n', argsDate),
		previousMonthAndYear = lang:formatDate('F Y', firstOfMonth .. ' -1 month'),
		nextMonthAndYear = lang:formatDate('F Y', firstOfMonth .. ' +1 month'),
		day = tonumber(lang:formatDate('j', argsDate)),
		daysInMonth = tonumber(lang:formatDate('j', firstOfMonth .. ' +1 month -1 day')),
		-- weekday of the first day of the month
		-- make compatible with Lua tables so we add 1. Sunday = 1, Saturday = 7.
		firstWeekday = tonumber(lang:formatDate('w', firstOfMonth)) + 1
	}
end

function makeDayStrings(dateStuff)
	local calStrings = {}
	local currentDay = dateStuff.day
	local currentMonth = dateStuff.month
	local currentYear = dateStuff.year
	
	for day = 1, dateStuff.daysInMonth do
		if dateStuff.argsDate then
			table.insert(calStrings, string.format(
				currentYear,
				currentMonth,
				day,
				day
			))
		else
			table.insert(calStrings, tostring(day))
		end
	end
	
	return calStrings
end

-- simple function to read the subpage with events
function events(page)
	local data = require(page)
	
	return data
end

function exportTable(dayStrings, dateStuff, page)
	-- generates the calendar HTML.
	local monthAndYear = dateStuff.monthAndYear
	local root = mw.html.create('table')
	root:attr('id', 'calendar')
		:tag('tr')
			:tag('th'):attr('colspan', 7):wikitext(monthAndYear)

	-- day of week headings
	local dayHeadingRow = root:tag('tr'):addClass('calendar-head')
	local weekdays = {'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'}
	for _, weekday in ipairs(weekdays) do
		dayHeadingRow:tag('th'):wikitext(weekday)
	end

	-- days
	-- tracks the number of day cells. Negative values used for initial blank cells.
	local cellCount = 1 - dateStuff.firstWeekday
	while cellCount < #dayStrings do -- Weekly rows
		local weeklyRow = root:tag('tr')
		
		for i = 1, 7 do -- Always make 7 cells.
			cellCount = cellCount + 1
			-- Use a blank cell if there is no corresponding dateString
			local dayString = dayStrings[cellCount] or ""
			local cellDay
			
			if dayString == tostring(dateStuff.day) then 
				cellDay = "cell-calendar-today" 
			else 
				cellDay = "cell-calendar" 
			end
			
			-- quantity of events in a specific day
			local eventData = events(page)[tonumber(dateStuff.monthNumber)][cellCount]
			if not eventData then
				eventData = ""
			else
				eventData = "<div>".. #eventData .."</div>"
			end
			
			weeklyRow:tag('td'):addClass(cellDay):wikitext(dayString, eventData)
		end
	end
	
	return tostring(root)
end

function exportList(dayStrings, dateStuff, page)
	local root = mw.html.create('ul')
	root:attr("id", "calendar-list")
	
	local eventData = events(page)
	
	for day, event in pairs(eventData[tonumber(dateStuff.monthNumber)]) do
		-- had to add a manual <ul> because I couldn't find a way to loop AND
		-- nest without doing annoying workarounds
		root:tag("li"):wikitext("Day " .. day .. "<ul>")
		
		for _, specificEvent in pairs(event) do
			root:wikitext("<li>" .. specificEvent .. "</li>")
		end
		root:wikitext("</ul>")
	end
	
	return tostring(root)
end

-- the actual calendar
function p.calendar(frame)
	local argsDate = frame.args["date"] -- date in Y-M
	local events = frame.args["events"] -- loads the event subpage
	
	local dateStuff = getDateStuff(argsDate)
	return exportTable(makeDayStrings(dateStuff), dateStuff, events)
end

-- the list of events in the month
function p.list(frame)
	local argsDate = frame.args["date"] -- date in Y-M
	local events = frame.args["events"] -- loads the event subpage
	
	local dateStuff = getDateStuff(argsDate)
	return exportList(makeDayStrings(dateStuff), dateStuff, events)
end

return p