Difference between revisions of "Module:Sidebar"
Jump to navigation
Jump to search
blackwiki>Jackmcbarn (prevent bad navbars from appearing) |
blackwiki>Matt Fitzpatrick (tableless layout (div instead of table)) |
||
Line 31: | Line 31: | ||
if not child then | if not child then | ||
root = root | root = root | ||
− | :tag(' | + | :tag('div') |
+ | :attr('role', args.role) | ||
+ | :attr('aria-labelledby', args.outertitle and mw.uri.anchorEncode(args.outertitle) or args.title and mw.uri.anchorEncode(args.title)) | ||
+ | :attr('aria-label', (args.outertitle or args.title) and nil or 'Sidebar') | ||
:addClass('vertical-navbox') | :addClass('vertical-navbox') | ||
:addClass(args.wraplinks ~= 'true' and 'nowraplinks' or nil) | :addClass(args.wraplinks ~= 'true' and 'nowraplinks' or nil) | ||
:addClass(args.bodyclass or args.class) | :addClass(args.bodyclass or args.class) | ||
+ | :css('position', 'relative') | ||
+ | :css('clear', args.float == 'none' and 'both' or args.float or 'right') | ||
:css('float', args.float or 'right') | :css('float', args.float or 'right') | ||
− | :css(' | + | :css('box-sizing', 'border-box') |
+ | :css('margin-left', args.float == 'right' and '1em' or nil) | ||
+ | :css('margin-right', args.float == 'left' and '1em' or nil) | ||
+ | :css('margin-bottom', '1em') | ||
:css('width', args.width or '22.0em') | :css('width', args.width or '22.0em') | ||
− | :css(' | + | :css('border', '1px solid #aaa') |
+ | :css('padding', '0.3em 0.5em') | ||
:css('background', '#f9f9f9') | :css('background', '#f9f9f9') | ||
− | |||
− | |||
− | |||
− | |||
:css('line-height', '1.4em') | :css('line-height', '1.4em') | ||
:css('font-size', '88%') | :css('font-size', '88%') | ||
+ | :css('text-align', 'center') | ||
:cssText(args.bodystyle or args.style) | :cssText(args.bodystyle or args.style) | ||
if args.outertitle then | if args.outertitle then | ||
root | root | ||
− | :tag(' | + | :css('margin-top', '1.6em') |
+ | :tag('div') | ||
+ | :attr('id', mw.uri.anchorEncode(args.outertitle)) | ||
:addClass(args.outertitleclass) | :addClass(args.outertitleclass) | ||
− | :css(' | + | :css('position', 'absolute') |
+ | :css('top', '-1.4em') | ||
+ | :css('left', '0') | ||
+ | :css('width', '100%') | ||
:css('font-size', '125%') | :css('font-size', '125%') | ||
:css('line-height', '1.2em') | :css('line-height', '1.2em') | ||
Line 61: | Line 72: | ||
if args.topimage then | if args.topimage then | ||
− | local | + | local imageContainer = root:tag('div') |
− | + | imageContainer | |
:addClass(args.topimageclass) | :addClass(args.topimageclass) | ||
:css('padding', '0.4em 0') | :css('padding', '0.4em 0') | ||
Line 70: | Line 81: | ||
if args.topcaption then | if args.topcaption then | ||
− | + | imageContainer | |
:tag('div') | :tag('div') | ||
:css('padding-top', '0.2em') | :css('padding-top', '0.2em') | ||
Line 81: | Line 92: | ||
if args.pretitle then | if args.pretitle then | ||
root | root | ||
− | :tag(' | + | :tag('div') |
− | + | :addClass(args.pretitleclass) | |
− | + | :cssText(args.basestyle) | |
− | + | :css('padding-top', args.topimage and '0.2em' or '0.4em') | |
− | + | :css('line-height', '1.2em') | |
− | + | :cssText(args.pretitlestyle) | |
− | + | :wikitext(args.pretitle) | |
− | |||
end | end | ||
Line 97: | Line 107: | ||
root | root | ||
:wikitext(args.title) | :wikitext(args.title) | ||
− | |||
else | else | ||
root | root | ||
− | :tag(' | + | :tag('div') |
− | : | + | :attr('id', (args.outertitle or args.pretitle) and nil or mw.uri.anchorEncode(args.title)) |
− | + | :addClass(args.titleclass) | |
− | + | :cssText(args.basestyle) | |
− | + | :css('padding', '0.2em 0.4em 0.2em') | |
− | + | :css('padding-top', args.pretitle and 0) | |
− | + | :css('font-size', '145%') | |
− | + | :css('line-height', '1.2em') | |
− | + | :css('font-weight', 'bold') | |
− | + | :cssText(args.titlestyle) | |
+ | :wikitext(args.title) | ||
end | end | ||
end | end | ||
if args.image then | if args.image then | ||
− | local | + | local imageContainer = root:tag('div') |
− | + | imageContainer | |
:addClass(args.imageclass) | :addClass(args.imageclass) | ||
:css('padding', '0.2em 0 0.4em') | :css('padding', '0.2em 0 0.4em') | ||
Line 123: | Line 133: | ||
if args.caption then | if args.caption then | ||
− | + | imageContainer | |
:tag('div') | :tag('div') | ||
:css('padding-top', '0.2em') | :css('padding-top', '0.2em') | ||
Line 134: | Line 144: | ||
if args.above then | if args.above then | ||
root | root | ||
− | :tag(' | + | :tag('div') |
− | + | :addClass(args.aboveclass) | |
− | + | :css('padding', '0.3em 0.4em 0.3em') | |
− | + | :css('font-weight', 'bold') | |
− | + | :cssText(args.abovestyle) | |
− | + | :newline() -- newline required for bullet-points to work | |
− | + | :wikitext(args.above) | |
− | |||
end | end | ||
− | local | + | local parameterNumbers = {} |
− | for k, | + | for k, _ in pairs(args) do |
k = '' .. k | k = '' .. k | ||
local num = k:match('^heading(%d+)$') or k:match('^content(%d+)$') | local num = k:match('^heading(%d+)$') or k:match('^content(%d+)$') | ||
− | if num then table.insert( | + | if num then table.insert(parameterNumbers, tonumber(num)) end |
end | end | ||
− | table.sort( | + | table.sort(parameterNumbers) |
-- remove duplicates from the list (e.g. 3 will be duplicated if both heading3 and content3 are specified) | -- remove duplicates from the list (e.g. 3 will be duplicated if both heading3 and content3 are specified) | ||
− | for i = # | + | for i = #parameterNumbers, 1, -1 do |
− | if | + | if parameterNumbers[i] == parameterNumbers[i - 1] then |
− | table.remove( | + | table.remove(parameterNumbers, i) |
end | end | ||
end | end | ||
− | for i, num in ipairs( | + | for i, num in ipairs(parameterNumbers) do |
local heading = args['heading' .. num] | local heading = args['heading' .. num] | ||
if heading then | if heading then | ||
root | root | ||
− | :tag(' | + | :tag('div') |
− | + | :addClass(args.headingclass) | |
− | + | :css('padding', '0.1em') | |
− | + | :css('font-weight', 'bold') | |
− | + | :cssText(args.basestyle) | |
− | + | :cssText(args.headingstyle) | |
− | + | :cssText(args['heading' .. num .. 'style']) | |
− | + | :newline() | |
− | + | :wikitext(heading) | |
end | end | ||
Line 176: | Line 185: | ||
if content then | if content then | ||
root | root | ||
− | :tag(' | + | :tag('div') |
− | + | :addClass(args.contentclass) | |
− | + | :css('padding', i == #parameterNumbers and '0 0.1em' or '0 0.1em 0.4em') -- no bottom padding on last content | |
− | + | :cssText(args.contentstyle) | |
− | + | :cssText(args['content' .. num .. 'style']) | |
− | + | :newline() | |
− | + | :wikitext(content) | |
− | + | :done() | |
− | + | :newline() -- Without a linebreak after the </td>, a nested list like "* {{hlist| ...}}" doesn't parse correctly. | |
− | |||
end | end | ||
end | end | ||
Line 191: | Line 199: | ||
if args.below then | if args.below then | ||
root | root | ||
− | :tag(' | + | :tag('div') |
− | : | + | :addClass(args.belowclass) |
− | + | :css('margin-top', '0.4em') | |
− | + | :css('padding', '0.3em 0.4em 0.3em') | |
− | + | :css('font-weight', 'bold') | |
− | + | :cssText(args.belowstyle) | |
− | + | :newline() | |
− | + | :wikitext(args.below) | |
end | end | ||
Line 205: | Line 213: | ||
if navbarArg ~= 'none' and navbarArg ~= 'off' and (args.name or frame:getParent():getTitle():gsub('/sandbox$', '') ~= 'Template:Sidebar') then | if navbarArg ~= 'none' and navbarArg ~= 'off' and (args.name or frame:getParent():getTitle():gsub('/sandbox$', '') ~= 'Template:Sidebar') then | ||
root | root | ||
− | :tag(' | + | :tag('div') |
− | + | :css('text-align', 'right') | |
− | + | :css('font-size', '115%') | |
− | + | :cssText(args.navbarstyle or args.tnavbarstyle) | |
− | + | :wikitext(navbar{ | |
− | + | args.name, | |
− | + | mini = 1, | |
− | + | fontstyle = args.navbarfontstyle or args.tnavbarfontstyle | |
− | + | }) | |
− | |||
end | end | ||
end | end |
Revision as of 00:09, 3 June 2017
![]() | This Lua module is used on 235,000+ pages. To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them. Transclusion count updated automatically (see documentation). |
![]() | 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 implements the templates {{sidebar}} and {{sidebar with collapsible lists}}. See the individual template pages for documentation.
--
-- This module implements {{Sidebar}}
--
require('Module:No globals')
local p = {}
local getArgs = require('Module:Arguments').getArgs
local navbar = require('Module:Navbar')._navbar
local function trimAndAddAutomaticNewline(s)
-- For compatibility with the original {{sidebar with collapsible lists}}
-- implementation, which passed some parameters through {{#if}} to trim
-- their whitespace. This also triggered the automatic newline behavior.
-- ([[meta:Help:Newlines and spaces#Automatic newline]])
s = mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1")
if mw.ustring.find(s, '^[#*:;]') or mw.ustring.find(s, '^{|') then
return '\n' .. s
else
return s
end
end
function p.sidebar(frame, args)
if not args then
args = getArgs(frame)
end
local root = mw.html.create()
local child = args.child and mw.text.trim(args.child) == 'yes'
if not child then
root = root
:tag('div')
:attr('role', args.role)
:attr('aria-labelledby', args.outertitle and mw.uri.anchorEncode(args.outertitle) or args.title and mw.uri.anchorEncode(args.title))
:attr('aria-label', (args.outertitle or args.title) and nil or 'Sidebar')
:addClass('vertical-navbox')
:addClass(args.wraplinks ~= 'true' and 'nowraplinks' or nil)
:addClass(args.bodyclass or args.class)
:css('position', 'relative')
:css('clear', args.float == 'none' and 'both' or args.float or 'right')
:css('float', args.float or 'right')
:css('box-sizing', 'border-box')
:css('margin-left', args.float == 'right' and '1em' or nil)
:css('margin-right', args.float == 'left' and '1em' or nil)
:css('margin-bottom', '1em')
:css('width', args.width or '22.0em')
:css('border', '1px solid #aaa')
:css('padding', '0.3em 0.5em')
:css('background', '#f9f9f9')
:css('line-height', '1.4em')
:css('font-size', '88%')
:css('text-align', 'center')
:cssText(args.bodystyle or args.style)
if args.outertitle then
root
:css('margin-top', '1.6em')
:tag('div')
:attr('id', mw.uri.anchorEncode(args.outertitle))
:addClass(args.outertitleclass)
:css('position', 'absolute')
:css('top', '-1.4em')
:css('left', '0')
:css('width', '100%')
:css('font-size', '125%')
:css('line-height', '1.2em')
:css('font-weight', 'bold')
:cssText(args.outertitlestyle)
:wikitext(args.outertitle)
end
if args.topimage then
local imageContainer = root:tag('div')
imageContainer
:addClass(args.topimageclass)
:css('padding', '0.4em 0')
:cssText(args.topimagestyle)
:wikitext(args.topimage)
if args.topcaption then
imageContainer
:tag('div')
:css('padding-top', '0.2em')
:css('line-height', '1.2em')
:cssText(args.topcaptionstyle)
:wikitext(args.topcaption)
end
end
if args.pretitle then
root
:tag('div')
:addClass(args.pretitleclass)
:cssText(args.basestyle)
:css('padding-top', args.topimage and '0.2em' or '0.4em')
:css('line-height', '1.2em')
:cssText(args.pretitlestyle)
:wikitext(args.pretitle)
end
end
if args.title then
if child then
root
:wikitext(args.title)
else
root
:tag('div')
:attr('id', (args.outertitle or args.pretitle) and nil or mw.uri.anchorEncode(args.title))
:addClass(args.titleclass)
:cssText(args.basestyle)
:css('padding', '0.2em 0.4em 0.2em')
:css('padding-top', args.pretitle and 0)
:css('font-size', '145%')
:css('line-height', '1.2em')
:css('font-weight', 'bold')
:cssText(args.titlestyle)
:wikitext(args.title)
end
end
if args.image then
local imageContainer = root:tag('div')
imageContainer
:addClass(args.imageclass)
:css('padding', '0.2em 0 0.4em')
:cssText(args.imagestyle)
:wikitext(args.image)
if args.caption then
imageContainer
:tag('div')
:css('padding-top', '0.2em')
:css('line-height', '1.2em')
:cssText(args.captionstyle)
:wikitext(args.caption)
end
end
if args.above then
root
:tag('div')
:addClass(args.aboveclass)
:css('padding', '0.3em 0.4em 0.3em')
:css('font-weight', 'bold')
:cssText(args.abovestyle)
:newline() -- newline required for bullet-points to work
:wikitext(args.above)
end
local parameterNumbers = {}
for k, _ in pairs(args) do
k = '' .. k
local num = k:match('^heading(%d+)$') or k:match('^content(%d+)$')
if num then table.insert(parameterNumbers, tonumber(num)) end
end
table.sort(parameterNumbers)
-- remove duplicates from the list (e.g. 3 will be duplicated if both heading3 and content3 are specified)
for i = #parameterNumbers, 1, -1 do
if parameterNumbers[i] == parameterNumbers[i - 1] then
table.remove(parameterNumbers, i)
end
end
for i, num in ipairs(parameterNumbers) do
local heading = args['heading' .. num]
if heading then
root
:tag('div')
:addClass(args.headingclass)
:css('padding', '0.1em')
:css('font-weight', 'bold')
:cssText(args.basestyle)
:cssText(args.headingstyle)
:cssText(args['heading' .. num .. 'style'])
:newline()
:wikitext(heading)
end
local content = args['content' .. num]
if content then
root
:tag('div')
:addClass(args.contentclass)
:css('padding', i == #parameterNumbers and '0 0.1em' or '0 0.1em 0.4em') -- no bottom padding on last content
:cssText(args.contentstyle)
:cssText(args['content' .. num .. 'style'])
:newline()
:wikitext(content)
:done()
:newline() -- Without a linebreak after the </td>, a nested list like "* {{hlist| ...}}" doesn't parse correctly.
end
end
if args.below then
root
:tag('div')
:addClass(args.belowclass)
:css('margin-top', '0.4em')
:css('padding', '0.3em 0.4em 0.3em')
:css('font-weight', 'bold')
:cssText(args.belowstyle)
:newline()
:wikitext(args.below)
end
if not child then
local navbarArg = args.navbar or args.tnavbar
if navbarArg ~= 'none' and navbarArg ~= 'off' and (args.name or frame:getParent():getTitle():gsub('/sandbox$', '') ~= 'Template:Sidebar') then
root
:tag('div')
:css('text-align', 'right')
:css('font-size', '115%')
:cssText(args.navbarstyle or args.tnavbarstyle)
:wikitext(navbar{
args.name,
mini = 1,
fontstyle = args.navbarfontstyle or args.tnavbarfontstyle
})
end
end
return tostring(root)
end
function p.collapsible(frame)
local args = getArgs(frame)
args.abovestyle = 'border-top: 1px solid #aaa; border-bottom: 1px solid #aaa;' .. (args.abovestyle or '')
args.belowstyle = 'border-top: 1px solid #aaa; border-bottom: 1px solid #aaa;' .. (args.belowstyle or '')
args.navbarstyle = 'padding-top: 0.6em;' .. (args.navbarstyle or args.tnavbarstyle or '')
if not args.name and frame:getParent():getTitle():gsub('/sandbox$', '') == 'Template:Sidebar with collapsible lists' then
args.navbar = 'none'
end
local contentArgs = {}
for k, v in pairs(args) do
local num = string.match(k, '^list(%d+)$')
if num then
local expand = args.expanded and (args.expanded == 'all' or args.expanded == args['list' .. num .. 'name'])
local row = mw.html.create('div')
row
:addClass('NavFrame')
:addClass((not expand) and 'collapsed' or nil)
:css('border', 'none')
:css('padding', 0)
:cssText(args.listframestyle)
:cssText(args['list' .. num .. 'framestyle'])
:tag('div')
:addClass('NavHead')
:addClass(args.listtitleclass)
:css('font-size', '105%')
:css('background', 'transparent')
:css('text-align', 'left')
:cssText(args.basestyle)
:cssText(args.listtitlestyle)
:cssText(args['list' .. num .. 'titlestyle'])
:wikitext(trimAndAddAutomaticNewline(args['list' .. num .. 'title'] or 'List'))
:done()
:tag('div')
:addClass('NavContent')
:addClass(args.listclass)
:addClass(args['list' .. num .. 'class'])
:css('font-size', '105%')
:css('padding', '0.2em 0 0.4em')
:css('text-align', 'center')
:cssText(args.liststyle)
:cssText(args['list' .. num .. 'style'])
:wikitext(trimAndAddAutomaticNewline(args['list' .. num]))
contentArgs['content' .. num] = tostring(row)
end
end
for k, v in pairs(contentArgs) do
args[k] = v
end
return p.sidebar(frame, args)
end
return p