模組:Bar
外观
Module:Bar可以為棒形圖產生有色的棒形,應用於較頂層的模板中。
用法
數據系
在調用該模塊時,須提供一系列數值。
系列由多組 == 組成,每組有2﹣3個參數:數值、顏色以及可選填的提示信息。
例如:
{{#invoke:bar|format|4,green,完成|2,gray,進行中|4,#FCC,未完成}}
總數
可以指定棒形中有多少個數值。如果指定的數量比實際提供的數量多,模塊就會在末端加入相應的空白。例如:
{{#invoke:bar|format|7,green,完成|total=10}} {{pb}} {{#invoke:bar|format|4,green,完成|total=10}} {{pb}} {{#invoke:bar|format|2,green,完成|total=10}}
寬度
默認寬度設為100%,但可換做任何CSS寬度值。例如:
{{#invoke:bar|format|7,green,完成|width=5em}} {{pb}} {{#invoke:bar|format|7,green,完成|width=15em}}
CSS
可用CSS改變棒形外觀。例如:
{{#invoke:bar|format|7,green,完成|total=10|width=30em|barCSS=border:1px solid #CCC}}
例子
完成度
{| role="presentation" |{{#invoke:bar|format|7,green,完成|total=10|width=30em|barCSS=border:1px solid #CCC;}} |{{#expr:7 / 10 * 100}}% |}
70% |
層疊棒形圖
{| class="wikitable" |+ 支出與收入 |- | 2011年 | {{#invoke:bar|format|100,red,支出|50,green,收入|total=170|width=30em}} |- | 2012年 | {{#invoke:bar|format|75,red,支出|90,green,收入|total=170|width=30em}} |}
2011年 | ||||
2012年 |
分組棒形圖
{| class="wikitable" |+ 支出與收入 |- | 2011 | {{#invoke:bar|format|150,green,收入|total=160|width=15em}} {{#invoke:bar|format|100,red,支出|total=160|width=15em}} |- | 2012 | {{#invoke:bar|format|160,green,收入|total=160|width=15em}} {{#invoke:bar|format|75,red,支出|total=160|width=15em}} |}
2011 | |||||
2012 |
-- https://meta.wikimedia.org/wiki/Module:Bar
local p = {}
--##########
--## Public functions
--##########
-- the main entry point
function p.format( frame )
-- extract configuration
local width = frame.args['width'] or '100%'
local barCSS = frame.args['barCSS'] or ''
local zeroWidth = frame.args['zeroWidth'] or '1px'
-- extract bar series from arguments like 'value,color,title'
local series = {}
for key, spec in ipairs(frame.args) do
spec = mw.text.split(spec, ',')
local data = {value = tonumber(spec[1] or 0), color = spec[2] or '#CCC', title = spec[3] or ''}
if data['value'] > 0 then
table.insert(series, data)
end
end
-- calculate total
local total = tonumber(frame.args['total'] or 0)
local seriesTotal = 0
for k,v in ipairs(series) do
seriesTotal = seriesTotal + v['value']
end
if total < seriesTotal then
total = seriesTotal
end
-- inject empty series for uncharted values
if(seriesTotal < total) then
table.insert(series, {value = total - seriesTotal, color = 'transparent', title = ''})
end
-- inject ratios
for k,v in ipairs(series) do
v['total'] = total
v['ratio'] = getRatio(v['value'], total)
if v['ratio'] == 0 then
v['width'] = zeroWidth
end
end
return format(series, total, width, barCSS)
end
--##########
--## Private functions
--##########
-- get the markup for a bar
function format(series, total, width, barCSS)
result = '<table style="width:' .. width .. ';' .. barCSS .. '" cellspacing="0"><tr>'
for k, v in pairs(series) do
result = result .. formatSeries(v)
end
result = result .. '</tr></table>'
return result
end
-- get the markup to format a series
function formatSeries(series)
-- set width
local width = series.width
if not(width) then
width = series.ratio .. '%'
end
-- format
local result = mw.ustring.format('<td title="%s" style="width:%s; height:1em; padding:0; background:%s;" data-value="%s"></td>', series.title, width, series.color, series.value)
return result
end
-- get the percentage ratio of two numbers
function getRatio(value, total)
if(total == 0) then
error('the total for a series cannot be zero')
end
return math.floor(value / total * 10000) / 100
end
return p