Module:Bar/sandbox: Difference between revisions
Appearance
Content deleted Content added
Fixed left/right spacing of caption and footer |
Made module Object-Oriented with a bit of Python flavor |
||
Line 1: | Line 1: | ||
local getArgs = require('Module:Arguments').getArgs |
local getArgs = require('Module:Arguments').getArgs |
||
local |
local BarBox = { |
||
_css = 'Module:Bar box/styles.css', |
|||
float = 'none', |
|||
backgroundcolor = 'white', |
|||
borderwidth = '1', |
|||
-- width = 'auto', |
|||
barwidth = '100px', |
|||
-- lineheight = '1.6', |
|||
-- titlebar = 'none' |
|||
} |
|||
BarBox.__index = BarBox |
|||
⚫ | |||
BarBox.__tostring = function (self) |
|||
⚫ | |||
return self:html() |
|||
⚫ | |||
local metatable = { |
|||
__call = function (cls, args) |
|||
local self = mw.clone(args) or {} |
|||
setmetatable(self, cls) |
|||
⚫ | |||
⚫ | |||
} |
|||
setmetatable(BarBox, metatable) |
|||
function BarBox.create(args) |
|||
return BarBox{ |
|||
css = args.css, |
|||
⚫ | |||
backgroundcolor = args.backgroundcolor, |
|||
borderwidth = args.borderwidth, |
|||
style = args.style, |
|||
width = tonumber(args.width) and args.width .. 'px' or args.width and args.width:lower(), |
|||
barwidth = tonumber(args.barwidth) and args.barwidth .. 'px' or args.barwidth and args.barwidth:lower(), |
|||
lineheight = args.lineheight, |
|||
title = args.title, |
|||
titlebar = args.titlebar, |
|||
left1 = args.left1, |
|||
left2 = args.left2, |
|||
right1 = args.right1, |
|||
right2 = args.right2, |
|||
bars = args.bars, |
|||
caption = args.caption, -- deprecated |
|||
⚫ | |||
} |
|||
⚫ | |||
⚫ | |||
⚫ | |||
local alignClasses |
|||
function |
local function setAlign(align) |
||
alignClasses = {} |
|||
for i, d in ipairs( |
for i, d in ipairs(tDefaultAlign) do |
||
local a = align:sub(i, i) |
local a = align:sub(i, i) |
||
if a == 'l' then |
if a == 'l' then |
||
Line 17: | Line 63: | ||
error('unrecognized align[' .. i .. ']') |
error('unrecognized align[' .. i .. ']') |
||
end |
end |
||
alignClasses[i] = (a and ' class=bb-' .. a or '') .. '|' |
|||
end |
end |
||
end |
end |
||
function |
function BarBox:html() |
||
for key, value in pairs(args) do |
|||
if ({float=1, width=1, barwidth=1})[key] then -- if key in {...} |
|||
args[key] = value:lower() |
|||
⚫ | |||
⚫ | |||
local output = {} |
local output = {} |
||
local frame = mw.getCurrentFrame() |
local frame = mw.getCurrentFrame() |
||
output[1] = frame:extensionTag('templatestyles', '', {src= |
output[1] = frame:extensionTag('templatestyles', '', {src=self._css}) .. '\n' |
||
output[2] = |
output[2] = self.css and frame:extensionTag('templatestyles', '', {src=self.css}) .. '\n' or '' |
||
local class = 'barbox' |
local class = 'barbox' |
||
if |
if self.float == 'left' or self.float == 'right' then |
||
class = class .. ' t' .. |
class = class .. ' t' .. self.float |
||
⚫ | |||
local function _width(width, default) |
|||
local w = width or default |
|||
if tonumber(w) then w = w .. 'px' end |
|||
⚫ | |||
end |
end |
||
output[3] = |
output[3] = |
||
'<div class="' .. class .. '" style="background:' .. |
'<div class="' .. class .. '" style="background:' .. self.backgroundcolor .. |
||
'; border:' .. |
'; border:' .. self.borderwidth .. 'px solid silver' .. |
||
( |
(self.float == 'center' and '; margin:0 auto' or '') .. |
||
'; width:' .. |
(self.width and '; width:' .. self.width or '') .. |
||
( |
(self.style and '; ' .. self.style or '') .. '">\n' .. |
||
'{|' .. ( |
'{|' .. (self.lineheight and ' style="line-height:' .. self.lineheight .. '"' or '') .. '\n' |
||
output[4] = |
output[4] = self.title and |
||
'|+ class=bb-default' .. ( |
'|+ class=bb-default' .. (self.titlebar and ' style="background:' .. self.titlebar .. '"' or '') .. ' |\n' .. self.title .. '\n' |
||
or '' |
or '' |
||
output[5] = '|- class=bb-default style="font-size:88%; min-height:4px"\n' |
output[5] = '|- class=bb-default style="font-size:88%; min-height:4px"\n' |
||
if not |
if not alignClasses then |
||
setAlign(sDefaultAlign) |
|||
end |
end |
||
output[6] = '!' .. ( |
output[6] = '!' .. (self.left2 and '' or 'colspan=2') .. alignClasses[1] .. (self.left1 or ' ') |
||
output[7] = |
output[7] = self.left2 and '!!' .. alignClasses[2] .. self.left2 or '' |
||
output[8] = '!!style="width:' .. |
output[8] = '!!style="width:' .. self.barwidth .. '"| ' |
||
output[9] = '!!' .. ( |
output[9] = '!!' .. (self.right2 and alignClasses[3] or 'colspan=2' .. alignClasses[4]) .. (self.right1 or ' ') |
||
output[10] = |
output[10] = self.right2 and '!!' .. alignClasses[4] .. self.right2 or '' |
||
alignClasses = nil |
|||
output[11] = '\n' |
output[11] = '\n' |
||
output[12] = |
output[12] = self.bars and self.bars .. '\n' or '' |
||
if |
if self.caption then |
||
output[15] = '\n[[Category:Pages using bar box with deprecated caption parameter]]' |
output[15] = '\n[[Category:Pages using bar box with deprecated caption parameter]]' |
||
⚫ | |||
else |
else |
||
output[15] = '' |
output[15] = '' |
||
end |
end |
||
output[13] = |
output[13] = self.footer and |
||
'|- class=bb-default\n| colspan=5 style="padding:5px 0" | ' .. |
'|- class=bb-default\n| colspan=5 style="padding:5px 0" | ' .. self.footer .. '\n' -- <p> is created if \n precedes the footer |
||
or '' |
or '' |
||
output[14] = '|}\n</div>\n' |
output[14] = '|}\n</div>\n' |
||
Line 84: | Line 118: | ||
end |
end |
||
function |
function BarBox._percent(args) |
||
local output = {} |
local output = {} |
||
local percentage = (args[3] or '0') .. '%' |
local percentage = (args[3] or '0') .. '%' |
||
Line 98: | Line 132: | ||
end |
end |
||
function |
function BarBox._pixel(args) |
||
local output = {} |
local output = {} |
||
local pixels = args[3] or '0' |
local pixels = args[3] or '0' |
||
Line 112: | Line 146: | ||
end |
end |
||
function |
function BarBox._stacked(args) |
||
⚫ | |||
local output = {} |
local output = {} |
||
Line 120: | Line 152: | ||
'|-class="mw-collapsible' .. (args.collapsed and ' mw-collapsed' or '') .. '" id=mw-customcollapsible-' .. args.id .. '\n' |
'|-class="mw-collapsible' .. (args.collapsed and ' mw-collapsed' or '') .. '" id=mw-customcollapsible-' .. args.id .. '\n' |
||
or '|-\n' |
or '|-\n' |
||
if not |
if not alignClasses then |
||
setAlign(args.align and args.align:lower() or sDefaultAlign) |
|||
end |
end |
||
output[2] = '|' .. (args.note1 and '' or 'colspan=2') .. |
output[2] = '|' .. (args.note1 and '' or 'colspan=2') .. alignClasses[1] .. (args[1] or ' ') |
||
output[3] = args.note1 and '||' .. |
output[3] = args.note1 and '||' .. alignClasses[2] .. args.note1 or '' |
||
output[4] = '||class=bb-b|' |
output[4] = '||class=bb-b|' |
||
Line 133: | Line 165: | ||
end |
end |
||
⚫ | |||
for i = 1, (len-2) / 2 do |
for i = 1, (len-2) / 2 do |
||
⚫ | |||
width = args[2*i + 2] or 0 |
width = args[2*i + 2] or 0 |
||
width = tonumber(('%.2f'):format(width)) |
width = tonumber(('%.2f'):format(width)) |
||
Line 142: | Line 174: | ||
title = args['title' .. i] and ' title="' .. args['title' .. i] .. '"' or '' |
title = args['title' .. i] and ' title="' .. args['title' .. i] .. '"' or '' |
||
background = args[2*i + 1] or 'gray' |
background = args[2*i + 1] or 'gray' |
||
⚫ | |||
output[i+4] = |
|||
⚫ | |||
end |
end |
||
end |
end |
||
output[#output+1] = '||' .. (args.note2 and |
output[#output+1] = '||' .. (args.note2 and alignClasses[3] or 'colspan=2' .. alignClasses[4]) .. (args[2] or ' ') |
||
output[#output+1] = args.note2 and '||' .. |
output[#output+1] = args.note2 and '||' .. alignClasses[4] .. args.note2 or '' |
||
return table.concat(output) |
return table.concat(output) |
||
end |
end |
||
function |
function BarBox._gap(args) |
||
local output = {} |
local output = {} |
||
local height = tonumber(args.height) and args.height .. 'px' or args.height or '10px' |
local height = tonumber(args.height) and args.height .. 'px' or args.height and args.height:lower() or '10px' |
||
output[1] = '|-\n' |
output[1] = '|-\n' |
||
Line 163: | Line 194: | ||
end |
end |
||
function |
function BarBox.box(frame) |
||
local args = getArgs(frame) |
local args = getArgs(frame) |
||
local box = BarBox.create(args) |
|||
return tostring(box) |
|||
end |
end |
||
function |
function BarBox.percent(frame) |
||
local args = getArgs(frame) |
local args = getArgs(frame) |
||
return |
return BarBox._percent(args) |
||
end |
end |
||
function |
function BarBox.pixel(frame) |
||
local args = getArgs(frame) |
local args = getArgs(frame) |
||
return |
return BarBox._pixel(args) |
||
end |
end |
||
function |
function BarBox.stacked(frame) |
||
local yesno = require('Module:Yesno') |
local yesno = require('Module:Yesno') |
||
local args = getArgs(frame, { |
local args = getArgs(frame, { |
||
Line 194: | Line 226: | ||
end |
end |
||
}) |
}) |
||
return |
return BarBox._stacked(args) |
||
end |
end |
||
function |
function BarBox.gap(frame) |
||
local args = getArgs(frame) |
local args = getArgs(frame) |
||
return |
return BarBox._gap(args) |
||
end |
end |
||
return |
return BarBox |
Revision as of 00:16, 2 March 2021
![]() | This is the module sandbox page for Module:Bar (diff). |
![]() | This module is rated as beta, and is ready for widespread use. It is still new and should be used with some caution to ensure the results are as expected. |
![]() | 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 module depends on the following other modules: |
![]() | This Lua module is used on many 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. |
{{Bar box}}, is used for construction of horizontal bar charts.
Usage
{{Bar box
|width = ''width of the graph'' (optional)
|barwidth= ''width of the bar area'' (optional, defaults to 100px)
|float = (left|right|none) (optional, defaults to none)
|title = ''title of the chart'' (optional)
|titlebar= ''title bar colour'' (optional, defaults to none)
|left1 = ''first left column header'' (optional)
|left2 = ''second left column header'' (optional)
|right1 = ''first right column header'' (optional)
|right2 = ''second right column header'' (optional)
|bars = ''chart contents'' (see below)
|caption = ''caption under the chart'' (optional)
}}
Alternatives to avoid Wikipedia's Post-expand include size limit
Pages with many boxes and charts may come close to or exceed Wikipedia's Post-expand include size limit. In these cases consider using Module:Bar as follows:
- {{Bar box}} → {{#invoke:Bar|box}}
- {{Bar percent}} → {{#invoke:Bar|percent}}
- {{Bar pixel}} → {{#invoke:Bar|pixel}}
- {{Bar log}} → {{#invoke:Bar|log}}
- {{Bar stacked}} → {{#invoke:Bar|stacked}}
- {{Bar gap}} → {{#invoke:Bar|gap}}
Tracking category
See also
- {{Vertical bar chart}}
- {{Bar chart}}
- {{Data bars}}
- WP:Graphs
local getArgs = require('Module:Arguments').getArgs
local BarBox = {
_css = 'Module:Bar box/styles.css',
float = 'none',
backgroundcolor = 'white',
borderwidth = '1',
-- width = 'auto',
barwidth = '100px',
-- lineheight = '1.6',
-- titlebar = 'none'
}
BarBox.__index = BarBox
BarBox.__tostring = function (self)
return self:html()
end
local metatable = {
__call = function (cls, args)
local self = mw.clone(args) or {}
setmetatable(self, cls)
return self
end
}
setmetatable(BarBox, metatable)
function BarBox.create(args)
return BarBox{
css = args.css,
float = args.float and args.float:lower(),
backgroundcolor = args.backgroundcolor,
borderwidth = args.borderwidth,
style = args.style,
width = tonumber(args.width) and args.width .. 'px' or args.width and args.width:lower(),
barwidth = tonumber(args.barwidth) and args.barwidth .. 'px' or args.barwidth and args.barwidth:lower(),
lineheight = args.lineheight,
title = args.title,
titlebar = args.titlebar,
left1 = args.left1,
left2 = args.left2,
right1 = args.right1,
right2 = args.right2,
bars = args.bars,
caption = args.caption, -- deprecated
footer = args.footer or args.caption
}
end
local sDefaultAlign = 'lrlr'
local tDefaultAlign = {false, 'r', false, 'r'}
local alignClasses
local function setAlign(align)
alignClasses = {}
for i, d in ipairs(tDefaultAlign) do
local a = align:sub(i, i)
if a == 'l' then
a = false
elseif a == 'd' then
a = d
elseif a ~= 'c' and a ~= 'r' then
error('unrecognized align[' .. i .. ']')
end
alignClasses[i] = (a and ' class=bb-' .. a or '') .. '|'
end
end
function BarBox:html()
local output = {}
local frame = mw.getCurrentFrame()
output[1] = frame:extensionTag('templatestyles', '', {src=self._css}) .. '\n'
output[2] = self.css and frame:extensionTag('templatestyles', '', {src=self.css}) .. '\n' or ''
local class = 'barbox'
if self.float == 'left' or self.float == 'right' then
class = class .. ' t' .. self.float
end
output[3] =
'<div class="' .. class .. '" style="background:' .. self.backgroundcolor ..
'; border:' .. self.borderwidth .. 'px solid silver' ..
(self.float == 'center' and '; margin:0 auto' or '') ..
(self.width and '; width:' .. self.width or '') ..
(self.style and '; ' .. self.style or '') .. '">\n' ..
'{|' .. (self.lineheight and ' style="line-height:' .. self.lineheight .. '"' or '') .. '\n'
output[4] = self.title and
'|+ class=bb-default' .. (self.titlebar and ' style="background:' .. self.titlebar .. '"' or '') .. ' |\n' .. self.title .. '\n'
or ''
output[5] = '|- class=bb-default style="font-size:88%; min-height:4px"\n'
if not alignClasses then
setAlign(sDefaultAlign)
end
output[6] = '!' .. (self.left2 and '' or 'colspan=2') .. alignClasses[1] .. (self.left1 or ' ')
output[7] = self.left2 and '!!' .. alignClasses[2] .. self.left2 or ''
output[8] = '!!style="width:' .. self.barwidth .. '"| '
output[9] = '!!' .. (self.right2 and alignClasses[3] or 'colspan=2' .. alignClasses[4]) .. (self.right1 or ' ')
output[10] = self.right2 and '!!' .. alignClasses[4] .. self.right2 or ''
alignClasses = nil
output[11] = '\n'
output[12] = self.bars and self.bars .. '\n' or ''
if self.caption then
output[15] = '\n[[Category:Pages using bar box with deprecated caption parameter]]'
else
output[15] = ''
end
output[13] = self.footer and
'|- class=bb-default\n| colspan=5 style="padding:5px 0" | ' .. self.footer .. '\n' -- <p> is created if \n precedes the footer
or ''
output[14] = '|}\n</div>\n'
return table.concat(output)
end
function BarBox._percent(args)
local output = {}
local percentage = (args[3] or '0') .. '%'
output[1] = '|-' .. (args.bg and 'style="background:' .. args.bg .. '"' or '') .. '\n'
output[2] = '|colspan=2 class=bb-min8|' .. (args[1] or ' ')
output[3] = '||class=bb-b|'
output[4] = '<div style="background:' .. (args[2] or 'gray') .. '; width:' .. percentage .. '">​</div>'
output[5] = '||' .. (args.note and '' or 'colspan=2 class=bb-r|') .. (args[4] or percentage)
output[6] = args.note and '||class=bb-r|' .. args.note or ''
return table.concat(output)
end
function BarBox._pixel(args)
local output = {}
local pixels = args[3] or '0'
output[1] = '|-' .. (args.bg and 'style="background:' .. args.bg .. '"' or '') .. '\n'
output[2] = '|colspan=2|' .. (args[1] or ' ')
output[3] = '||class=bb-b|'
output[4] = '<div style="background:' .. (args[2] or 'gray') .. '; width:' .. pixels .. 'px">​</div>'
output[5] = '||class="bb-min3' .. (args.note and '"' or ' bb-r" colspan=2') .. '|' .. (args[5] or pixels .. (args[4] or ''))
output[6] = args.note and '||class=bb-r|' .. args.note or ''
return table.concat(output)
end
function BarBox._stacked(args)
local output = {}
output[1] = args.id and
'|-class="mw-collapsible' .. (args.collapsed and ' mw-collapsed' or '') .. '" id=mw-customcollapsible-' .. args.id .. '\n'
or '|-\n'
if not alignClasses then
setAlign(args.align and args.align:lower() or sDefaultAlign)
end
output[2] = '|' .. (args.note1 and '' or 'colspan=2') .. alignClasses[1] .. (args[1] or ' ')
output[3] = args.note1 and '||' .. alignClasses[2] .. args.note1 or ''
output[4] = '||class=bb-b|'
local len = 4 -- can't use #args because of [[Module:Arguments#Known limitations]]
for k in pairs(args) do
local idx = tonumber(k) or 0
if idx > len then len = idx end
end
for i = 1, (len-2) / 2 do
local width, title, background
width = args[2*i + 2] or 0
width = tonumber(('%.2f'):format(width))
if width == 0 then
output[i+4] = ''
else
title = args['title' .. i] and ' title="' .. args['title' .. i] .. '"' or ''
background = args[2*i + 1] or 'gray'
output[i+4] = '<div' .. title .. ' style="background:' .. background .. '; width:' .. width .. 'px">​</div>'
end
end
output[#output+1] = '||' .. (args.note2 and alignClasses[3] or 'colspan=2' .. alignClasses[4]) .. (args[2] or ' ')
output[#output+1] = args.note2 and '||' .. alignClasses[4] .. args.note2 or ''
return table.concat(output)
end
function BarBox._gap(args)
local output = {}
local height = tonumber(args.height) and args.height .. 'px' or args.height and args.height:lower() or '10px'
output[1] = '|-\n'
output[2] = '|colspan=5 style="height:' .. height .. '"|' .. (args[1] or '')
return table.concat(output)
end
function BarBox.box(frame)
local args = getArgs(frame)
local box = BarBox.create(args)
return tostring(box)
end
function BarBox.percent(frame)
local args = getArgs(frame)
return BarBox._percent(args)
end
function BarBox.pixel(frame)
local args = getArgs(frame)
return BarBox._pixel(args)
end
function BarBox.stacked(frame)
local yesno = require('Module:Yesno')
local args = getArgs(frame, {
valueFunc = function (key, value)
if value then
if key == 'collapsed' then
return yesno(value)
end
value = mw.text.trim(value)
if value ~= '' then
return value
end
end
return nil
end
})
return BarBox._stacked(args)
end
function BarBox.gap(frame)
local args = getArgs(frame)
return BarBox._gap(args)
end
return BarBox