Module:Calendar widget explained

--Module to create Calendar widget

--

require('strict');local getArgs = require ('Module:Arguments').getArgs;

local lang_obj = mw.language.getContentLanguage;

local daysinmonth = local dayname = local dayabbr = for i, v in ipairs(dayname) do dayabbr[i] = v:sub(1, 2)end

local iso_dayname = local iso_dayabbr = for i, v in ipairs(iso_dayname) do iso_dayabbr[i] = v:sub(1, 2)end

local monthname = local monthabbr = if 0

#monthname then for m = 1, 12 do monthname[m] = lang_obj:formatDate ("F", '2019-' .. m); -- table of long month names monthabbr[m] = lang_obj:formatDate ("M", '2019-' .. m); -- table of abbreviated month names endend

----------------------------< I S _ L E A P >----------------------------------------------------------------

returns true when is a leapyear

local function is_leap (year) return '1'

lang_obj:formatDate ('L', tostring(year));end

----------------------------< D A Y _ O F _ W E E K >--------------------------------------------------------

returns 1 to 7; 1

Sunday; 1

Monday when iso true

local function day_of_week (year, month, day, iso) return iso and lang_obj:formatDate ('N', year .. '-' .. month .. '-' .. day) or -- ISO: 1 = monday lang_obj:formatDate ('w', year .. '-' .. month .. '-' .. day) + 1; -- 1 = sundayend

----------------------------< I S _ S E T >------------------------------------------------------------------

Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string.

local function is_set(var) return not (var

nil or var

);end

--[=[-------------------------< M A K E _ W I K I L I N K >---------------------------------------------------- Makes a wikilink; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if onlylink is provided, returns a wikilink in the form L; if neither are provided or link is omitted, returns anempty string.

]=]

local function make_wikilink (link, display) if is_set (link) then if is_set (display) then return table.concat ; else return table.concat ; end else return ; endend

----------------------------< G E T _ D I S P L A Y _ Y E A R >----------------------------------------------

returns year from props with prefixed and suffixed wikilink if appropriate; this function used for both yearlyand stand-alone calendars

local function get_display_year (props) local year_text = props.year; local lk_prefix = props.lk_pref_y or props.lk_pref; local lk_suffix = props.lk_suff_y or props.lk_suff;

if props.lk_y then -- if to be linked if lk_prefix or lk_suffix then -- when prefix or suffix, label year_text = make_wikilink ((lk_prefix or ) .. year_text .. (lk_suffix or ), year_text); else year_text = make_wikilink (year_text); -- just year end end return year_text;end

----------------------------< G E T _ D I S P L A Y _ M O N T H >--------------------------------------------

returns month from argument or props with wikilink, prefix, suffix ...

argument mnum is nil when rendering stand-alone calendar

local function get_display_month (mnum, props) local month_text = mnum or props.month_num; month_text = monthname[month_text];

local lk_prefix = props.lk_pref_m or props.lk_pref; local lk_suffix = props.lk_suff_m or props.lk_suff;

if props['lk_m&y'] then -- stand-alone month calendars only month_text = month_text .. ' ' .. props.year; -- composite month and year link end

if props.lk_m or props['lk_m&y'] then if lk_prefix or lk_suffix then -- when prefix or suffix, label month_text = make_wikilink ((lk_prefix or ) .. month_text .. (lk_suffix or ), month_text); else month_text = make_wikilink (month_text); -- just month name or composite month/year end end return month_text;end

----------------------------< G E T _ D I S P L A Y _ D A Y >------------------------------------------------

returns day with wikilink (month and day), link prefix, link suffix ... (text doesn't get prefix / suffix)

local function get_display_day (day_text, mnum, props) local lk_prefix = props.lk_pref_d or props.lk_pref; local lk_suffix = props.lk_suff_d or props.lk_suff;

if props.lk_d then local link_text = (lk_prefix or ) .. monthname[mnum] .. ' ' .. day_text .. (lk_suffix or ); day_text = make_wikilink (link_text, day_text); end return day_text;end

--

local function repeat_tags (tag, items, options) local tags = ; -- table of ... tag strings local opt_attr = options.attr or ; -- if options not supplied, use empty table local css_opts = options.css or ; for i, item in ipairs (items) do local repeat_tag = mw.html.create (tag); -- new td object repeat_tag :addClass (options.class) :attr (opt_attr) :css (css_opts) :wikitext (item) -- the item to be wrapped in ... :done -- close table.insert (tags, tostring (repeat_tag)); -- make a string of this object end

return table.concat (tags); -- concatenate them all togetherend

----------------------------< G E T _ R O W _ D A T E S >----------------------------------------------------

gets a week (row) of calendar dates each in its own ...; inserts iso week number tag ahead of column 1when props.iso_wk true.

local function get_row_dates (firstday, mnum, row, props) local options = ; -- table of otions for these td tags local td_items = ; -- table of ... tag strings local result = ; local hilite; local hilite_two; for col = 1, 7 do local dom = 7 * (row-1) + col + 1 - firstday -- calculate day of month for row/col position local day; if props.iso_wk and 1

col then -- when column 1, insert iso week number ahead of first 'dom' local iso_wk = lang_obj:formatDate ('W', props.year .. '-' .. mnum .. '-' .. ((1 > dom) and 1 or dom)); local css_opts = props.wknum_color and or ; table.insert (result, repeat_tags ('td',,)); end if dom < 1 or dom > daysinmonth[mnum] then day = " " -- before or after month, blank cell else day = get_display_day (dom, mnum, props); -- make wikilinks from month and day if required end

if props.today then -- highlight today's date when displayed if (props.year

props.this_ynum) and (mnum

props.this_mnum) and (dom

props.this_dnum) then hilite = col; end end if props.aday then -- highlight arbitrary date when displayed if (props.year

props.this_ynum) and (mnum

props.this_mnum) and (dom

props.this_dnum) then hilite_two = col; end end table.insert (td_items, day); end

for i, td_item in ipairs (td_items) do if i

hilite then table.insert (result, repeat_tags ('td',,)); else if i

hilite_two then table.insert (result, repeat_tags ('td',,)); end table.insert (result, repeat_tags ('td',, options)); end end

return table.concat (result);end

----------------------------< G E T _ W E E K _ D A Y _ H D R >----------------------------------------------

create header row of day-of-week abbreviations with title attributes

local function get_week_day_hdr (props) local headers = ; local css_opts = props.week_color and or

if props.iso_wk or props.iso then if props.iso_wk then table.insert (headers, repeat_tags ('th',,)); -- iso week header end for i, abbr in ipairs (iso_dayabbr) do table.insert (headers, repeat_tags ('th',,)); end else for i, abbr in ipairs (dayabbr) do table.insert (headers, repeat_tags ('th',,)); end end

return table.concat (headers);end

----------------------------< G E T _ M O N T H _ H D R >----------------------------------------------------

create main header row for month calendars, with or without year and with or without previous / next links

local function get_month_hdr (mnum, props) local result = ; local prev = ; local next = ; local hdr_year = ; local col_span = (props.iso_wk and 8) or 7; -- assume no prev/next

if not props.hide_year and props.month_num then -- props.month_num has value only for stand-alone month calendars hdr_year = get_display_year (props); -- if to be shown, add wikilink, etc when required end

if props.prevnext then prev = monthname[(0 < mnum-1) and mnum-1 or 12]; next = monthname[(13 > mnum+1) and mnum+1 or 1];

if is_set (hdr_year) then prev = prev .. ' ' .. ((0 < mnum-1) and hdr_year or hdr_year-1); -- january-1 = december previous year next = next .. ' ' .. ((13 > mnum+1) and hdr_year or hdr_year+1); -- december+1 = january next year end local link_text = (props.lk_pref_mprev or ) .. prev .. (props.lk_suff_mprev or ) prev = make_wikilink (link_text, '<<'); link_text = (props.lk_pref_mnext or ) .. next .. (props.lk_suff_mnext or ) next = make_wikilink (link_text, '>>');

table.insert (result, repeat_tags ('td',,)); -- insert prev now, insert next later col_span = col_span - 2; -- narrow the month year end

if props['lk_m&y'] then -- for composite links table.insert (result, repeat_tags ('th',,)); else table.insert (result, repeat_tags ('th',,)); end

if props.prevnext then table.insert (result, repeat_tags ('td',,)); end

return table.concat (result);end

----------------------------< D I S P L A Y M O N T H >------------------------------------------------------

generate the html to display a month calendar

local function display_month (mnum, props) if props.leap then daysinmonth[2] = 29 end local firstday = day_of_week (props.year, mnum, 1, props.iso); -- get first day number of the first day of the month; 1

Sunday

local table_css = ; if props.m_center then table_css = end if props.month_num then -- month_num only set when doing stand-alone month calendars table_css.border = '1px solid grey'; -- put this is styles.css as a separate class? end local month_cal = mw.html.create ('table'); month_cal :addClass ('mcal' .. (props.m_float_r and ' floatright' or )) -- float table right; leading space required to separate classes :css (table_css) :tag ('tr') -- for month name header :addClass ('mcalhdr') :css (props.title_color and or) :wikitext (get_month_hdr (mnum, props)) :done -- close :tag ('tr') -- for weekday header :addClass ('mcalhdr') :wikitext (get_week_day_hdr (props)) :done -- close

local numrows = math.ceil ((firstday + daysinmonth[mnum] - 1) / 7); -- calculate number of rows needed for this calendar for row = 1, numrows do month_cal :tag ('tr') -- for this week :addClass ('mcal') :wikitext (get_row_dates (firstday, mnum, row, props)); -- get dates for this week end month_cal:done -- close