Module:Current events calendar: Difference between revisions
noprint arrow links |
templatestyles, some cleaning of styles and whatnot |
||
Line 17: | Line 17: | ||
end |
end |
||
function |
local function getDateStuff(argsDate) |
||
local argsDate = nil |
|||
if (frame and frame.args and frame.args.year and frame.args.month) then |
|||
-- If a date is passed in, assume that the display page is an Archive page. |
|||
-- If no date passed in, assume that the display page is the current Current Events page |
|||
argsDate = frame.args.year .. "-" .. frame.args.month .. "-01" -- Construct a date, YYY-M-DD format. |
|||
end |
|||
local dateStuff = p.getDateStuff(argsDate) |
|||
local dayStrings = p.makeDayStrings(dateStuff) |
|||
return p.export(dayStrings, dateStuff) |
|||
end |
|||
function p.getDateStuff(argsDate) |
|||
--[[ |
--[[ |
||
Note: This function takes advantage of the formatDate's second argument to |
Note: This function takes advantage of the formatDate's second argument to |
||
Line 37: | Line 24: | ||
--]] |
--]] |
||
-- Gets date data. |
|||
local dateStuff = {} |
|||
local lang = mw.language.getContentLanguage() |
local lang = mw.language.getContentLanguage() |
||
dateStuff.argsDate = argsDate |
|||
--Year |
|||
local year = lang:formatDate('Y', argsDate) |
|||
year = tonumber(year) |
|||
dateStuff.year = year |
|||
-- Month |
|||
local month = lang:formatDate('F', argsDate) |
|||
dateStuff.month = month |
|||
-- Month and year |
|||
local monthAndYear = lang:formatDate('F Y', argsDate) |
|||
local firstOfMonth = lang:formatDate('01-m-Y', argsDate) |
local firstOfMonth = lang:formatDate('01-m-Y', argsDate) |
||
return { |
|||
dateStuff.monthAndYear = monthAndYear |
|||
argsDate = argsDate, |
|||
-- Previous month and year |
|||
year = tonumber(lang:formatDate('Y', argsDate)), |
|||
month = lang:formatDate('F', argsDate), |
|||
-- Next month and year |
|||
monthAndYear = lang:formatDate('F Y', argsDate), |
|||
previousMonthAndYear = lang:formatDate('F Y', firstOfMonth .. ' -1 month'), |
|||
-- Day |
|||
nextMonthAndYear = lang:formatDate('F Y', firstOfMonth .. ' +1 month'), |
|||
day = tonumber(lang:formatDate('j', argsDate)), |
|||
daysInMonth = tonumber(lang:formatDate('j', firstOfMonth .. ' +1 month -1 day')), |
|||
dateStuff.day = day |
|||
-- Weekday of the first day of the month |
|||
-- Make compatible with Lua tables so we add 1. Sunday = 1, Saturday = 7. |
|||
local daysInMonth = lang:formatDate('j', firstOfMonth .. ' +1 month -1 day') |
|||
firstWeekday = tonumber(lang:formatDate('w', firstOfMonth)) + 1 |
|||
daysInMonth = tonumber(daysInMonth) |
|||
} |
|||
dateStuff.daysInMonth = daysInMonth |
|||
-- Weekday of the first day of the month |
|||
local firstWeekday = lang:formatDate('w', firstOfMonth) -- Sunday = 0, Saturday = 6 |
|||
firstWeekday = tonumber(firstWeekday) |
|||
firstWeekday = firstWeekday + 1 -- Make compatible with Lua tables. Sunday = 1, Saturday = 7. |
|||
dateStuff.firstWeekday = firstWeekday |
|||
return dateStuff |
|||
end |
end |
||
function |
local function isLinkworthy(day, currentDay) |
||
-- Returns true if the calendar day should be linked, and false if not. Days |
|||
-- should be linked if they are the current day or if they are within the six |
|||
-- preceding days, as that is the number of items on the current events page. |
|||
return currentDay - 6 <= day and day <= currentDay |
|||
end |
|||
local function makeDayStrings(dateStuff) |
|||
local calStrings = {} |
local calStrings = {} |
||
local currentDay = dateStuff.day |
local currentDay = dateStuff.day |
||
local isLinkworthy = p.isLinkworthy |
|||
local currentMonth = dateStuff.month |
local currentMonth = dateStuff.month |
||
local currentYear = dateStuff.year |
local currentYear = dateStuff.year |
||
local makeDayLink = p.makeDayLink |
|||
for day = 1, dateStuff.daysInMonth do |
for day = 1, dateStuff.daysInMonth do |
||
if dateStuff.argsDate or isLinkworthy(day, currentDay) then |
if dateStuff.argsDate or isLinkworthy(day, currentDay) then |
||
table.insert(calStrings, string.format( |
|||
calStrings[#calStrings + 1] = makeDayLink(day, currentMonth, currentYear) |
|||
"[[#%d %s %d|%d]]", |
|||
currentYear, |
|||
currentMonth, |
|||
day, |
|||
day |
|||
)) |
|||
else |
else |
||
calStrings |
table.insert(calStrings, tostring(day)) |
||
end |
end |
||
end |
end |
||
Line 89: | Line 69: | ||
end |
end |
||
function |
local function export(dayStrings, dateStuff) |
||
-- Returns true if the calendar day should be linked, and false if not. |
|||
-- Days should be linked if they are the current day or if they are within the six |
|||
-- preceding days, as that is the number of items on the current events page. |
|||
if currentDay - 6 <= day and day <= currentDay then |
|||
return true |
|||
else |
|||
return false |
|||
end |
|||
end |
|||
function p.makeDayLink(day, month, year) |
|||
return string.format("'''[[#%d %s %d| %d ]]'''", year, month, day, day) |
|||
end |
|||
function p.export(dayStrings, dateStuff) |
|||
-- Generates the calendar HTML. |
-- Generates the calendar HTML. |
||
local monthAndYear = dateStuff.monthAndYear |
local monthAndYear = dateStuff.monthAndYear |
||
local root = mw.html.create('table') |
local root = mw.html.create('table') |
||
-- The next two lines help to make the table-layout-based Archive pages look good. When the |
|||
-- Archives have been converted to a grid-based layout, this logic can be removed, and the |
|||
-- corressponding CSS margin attribute can be simplified. |
|||
local temporaryMarginAdjustment = "auto !important" |
|||
if dateStuff.argsDate then temporaryMarginAdjustment = "8px 0 0 8px" end |
|||
root |
root |
||
:addClass(' |
:addClass('current-events-calendar') |
||
-- Make the table-layout-based Archive pages look good. When the Archives |
|||
:css{ |
|||
-- have been converted to a grid-based layout, this logic can be removed, |
|||
display = 'table', |
|||
-- and the corressponding CSS margin attribute can be simplified. |
|||
width = '100%', |
|||
:addClass(dateStuff.argsDate and 'current-events-calendar-archive') |
|||
float = 'initial', |
|||
['max-width'] = '350px', |
|||
margin = temporaryMarginAdjustment, |
|||
['text-align'] = 'center', |
|||
['background-color'] = '#f5faff', |
|||
border = '1px solid #cedff2' |
|||
} |
|||
-- Headings |
-- Headings |
||
:tag(' |
:tag('caption') |
||
: |
:tag('span') |
||
: |
:addClass('noprint') |
||
:wikitext(makeWikilink( |
|||
:css{['text-align'] = 'center'} |
|||
'Portal:Current events/' .. dateStuff.previousMonthAndYear, |
|||
:tag('span') |
|||
'◀' |
|||
)) |
|||
:wikitext(makeWikilink('Portal:Current events/' .. dateStuff.previousMonthAndYear, '◀')) |
|||
:done() |
|||
:done() |
:done() |
||
:tag(' |
:tag('span') |
||
:wikitext(makeWikilink( |
|||
:attr('colspan', '5') |
|||
'Portal:Current events/' .. monthAndYear, |
|||
:css{['text-align'] = 'center'} |
|||
monthAndYear |
|||
:wikitext(makeWikilink('Portal:Current events/' .. monthAndYear, monthAndYear)) |
|||
)) |
|||
:done() |
:done() |
||
:tag(' |
:tag('span') |
||
:addClass('noprint') |
|||
:css{['text-align'] = 'center'} |
|||
:wikitext(makeWikilink( |
|||
:tag('span') |
|||
'Portal:Current events/' .. dateStuff.nextMonthAndYear, |
|||
:addClass('noprint') |
|||
'▶' |
|||
:wikitext(makeWikilink('Portal:Current events/' .. dateStuff.nextMonthAndYear, '▶')) |
|||
)) |
|||
-- Day of week headings |
-- Day of week headings |
||
local dayHeadingRow = root:tag('tr') |
local dayHeadingRow = root:tag('tr') |
||
local weekdays = {'S', 'M', 'T', 'W', 'T', 'F', 'S'} |
local weekdays = {'S', 'M', 'T', 'W', 'T', 'F', 'S'} |
||
for |
for _, weekday in ipairs(weekdays) do |
||
dayHeadingRow:tag('th') |
dayHeadingRow:tag('th'):wikitext(weekday) |
||
:css{['width'] = '14%', ['text-align'] = 'center'} |
|||
:wikitext(weekday) |
|||
end |
end |
||
-- Days |
-- 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 |
while cellCount < #dayStrings do -- Weekly rows |
||
local weeklyRow = root:tag('tr') |
local weeklyRow = root:tag('tr') |
||
for i = 1, 7 do -- Always make 7 cells. |
for i = 1, 7 do -- Always make 7 cells. |
||
cellCount = cellCount + 1 |
cellCount = cellCount + 1 |
||
-- Use a blank cell if there is no corresponding dateString |
|||
local dayString = dayStrings[cellCount] or '' |
|||
weeklyRow:tag('td') |
|||
weeklyRow:tag('td'):wikitext(dayString) |
|||
:css{['text-align'] = 'center'} |
|||
:wikitext(dayString) |
|||
end |
end |
||
end |
end |
||
Line 171: | Line 124: | ||
if not dateStuff.argsDate then -- No footer necessary on Archive pages. |
if not dateStuff.argsDate then -- No footer necessary on Archive pages. |
||
root:tag('tr') |
root:tag('tr') |
||
:addClass('current-events-calendar-footer') |
|||
:addClass('noprint') |
:addClass('noprint') |
||
:tag('td') |
:tag('td') |
||
:attr('colspan', '7') |
:attr('colspan', '7') |
||
:wikitext(makeWikilink( |
|||
:css{['padding-top'] = '3px', ['padding-bottom'] = '5px', ['font-size'] = '78%', ['text-align'] = 'right'} |
|||
'Portal:Current events/' .. monthAndYear, |
|||
'More ' .. monthAndYear .. ' events... ' |
|||
)) |
|||
end |
end |
||
return tostring(root) |
return tostring(root) |
||
end |
|||
function p.main(frame) |
|||
local argsDate = nil |
|||
if frame and frame.args and frame.args.year and frame.args.month then |
|||
-- If a date is passed in, assume that the display page is an Archive page. |
|||
-- If no date passed in, assume that the display page is the current Current Events page |
|||
-- Construct a date, YYY-M-DD format. |
|||
argsDate = frame.args.year .. "-" .. frame.args.month .. "-01" |
|||
end |
|||
local dateStuff = getDateStuff(argsDate) |
|||
return frame:extensionTag{ |
|||
name = 'templatestyles', |
|||
args = { src = 'Module:Current events calendar/styles.css' } |
|||
} .. export(makeDayStrings(dateStuff), dateStuff) |
|||
end |
end |
||
Latest revision as of 16:07, 2 November 2021
![]() | This module is rated as ready for general use. It has reached a mature form and is thought to be relatively bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other Wikipedia resources as an option for new users to learn. To reduce server load and bad output, it should be improved by sandbox testing rather than repeated trial-and-error editing. |
![]() | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
![]() | This module uses TemplateStyles: |
![]() | This Lua module is used on approximately 540 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them. |
This module generates calendars for Portal:Current events and Category:Current events archives. The current day and the previous six days are linked to the corresponding section of the page. The module also supports archival calendars when month and year parameters are passed. Note that the Current Month version will only link the previous six days and will include a link of form: More June 2025 events....
Usage on Portal:Current events
{{#invoke:current events calendar|main}}
Usage on Category:Current events archives pages
{{#invoke:current events calendar|main|year=[four digit numerical year]|month=[One or two digit number from 1 to 12]}}
Example: Current Events front page version
This version assumes that it is displayed in a page that will set padding/margins/gutters in parent containing elements. It will expand to a maximum of 350px wide and remain centered in the column. It includes a link to the full month's page in the footer. Only the six most recent days of the month will have hyperlinks, reflecting the 6 most recent days of content on the Portal:Current events page.
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
Example: Current Events archive version
This version assumes that it is displayed in a page that uses a table-based layout and expect individual children to set their margins and padding. It will expand to a maximum of 350px wide and puts an 8px margin on the top and left side of the calendar. It has no footer. All days will have links to the appropriate section of the page it is displayed in.
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Sandbox version
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
-- This module renders the calendar seen on [[Portal:Current events]].
--[[
Incoming expected variables:
frame.args.year = Integer value for year
frame.args.month = Integer value for month, 1 based.
--]]
local p = {}
local function makeWikilink(link, display)
if display then
return string.format('[[%s|%s]]', link, display)
else
return string.format('[[%s]]', link)
end
end
local function getDateStuff(argsDate)
--[[
Note: This function takes advantage of the formatDate's second argument to
create data for the archival calendars. If the second arg (argsDate) is nil,
then formatDate assumes the current date/time.
--]]
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),
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
local function isLinkworthy(day, currentDay)
-- Returns true if the calendar day should be linked, and false if not. Days
-- should be linked if they are the current day or if they are within the six
-- preceding days, as that is the number of items on the current events page.
return currentDay - 6 <= day and day <= currentDay
end
local 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 or isLinkworthy(day, currentDay) then
table.insert(calStrings, string.format(
"[[#%d %s %d|%d]]",
currentYear,
currentMonth,
day,
day
))
else
table.insert(calStrings, tostring(day))
end
end
return calStrings
end
local function export(dayStrings, dateStuff)
-- Generates the calendar HTML.
local monthAndYear = dateStuff.monthAndYear
local root = mw.html.create('table')
root
:addClass('current-events-calendar')
-- Make the table-layout-based Archive pages look good. When the Archives
-- have been converted to a grid-based layout, this logic can be removed,
-- and the corressponding CSS margin attribute can be simplified.
:addClass(dateStuff.argsDate and 'current-events-calendar-archive')
-- Headings
:tag('caption')
:tag('span')
:addClass('noprint')
:wikitext(makeWikilink(
'Portal:Current events/' .. dateStuff.previousMonthAndYear,
'◀'
))
:done()
:tag('span')
:wikitext(makeWikilink(
'Portal:Current events/' .. monthAndYear,
monthAndYear
))
:done()
:tag('span')
:addClass('noprint')
:wikitext(makeWikilink(
'Portal:Current events/' .. dateStuff.nextMonthAndYear,
'▶'
))
-- Day of week headings
local dayHeadingRow = root:tag('tr')
local weekdays = {'S', 'M', 'T', 'W', 'T', 'F', 'S'}
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 ''
weeklyRow:tag('td'):wikitext(dayString)
end
end
-- Footer
if not dateStuff.argsDate then -- No footer necessary on Archive pages.
root:tag('tr')
:addClass('current-events-calendar-footer')
:addClass('noprint')
:tag('td')
:attr('colspan', '7')
:wikitext(makeWikilink(
'Portal:Current events/' .. monthAndYear,
'More ' .. monthAndYear .. ' events... '
))
end
return tostring(root)
end
function p.main(frame)
local argsDate = nil
if frame and frame.args and frame.args.year and frame.args.month then
-- If a date is passed in, assume that the display page is an Archive page.
-- If no date passed in, assume that the display page is the current Current Events page
-- Construct a date, YYY-M-DD format.
argsDate = frame.args.year .. "-" .. frame.args.month .. "-01"
end
local dateStuff = getDateStuff(argsDate)
return frame:extensionTag{
name = 'templatestyles',
args = { src = 'Module:Current events calendar/styles.css' }
} .. export(makeDayStrings(dateStuff), dateStuff)
end
return p