Modul:Diagram rozšířený
Používá se stejně jako Modul:Diagram, umožňuje však pouze koláčový graf (pozor, musí být stále uvedeno jako parametr při volání modulu) přidává však 2 nové parametry:
- float legendy = vlevo nebo vpravo; legenda bude napravo nebo nalevo od grafu samotného
- sirka legendy = šířka legendy v pixelech bez px na konci
--<syntaxhighlight lang="lua">
--[[
keywords are used for languages: they are the names of the actual
parameters of the template
]]
local keywords = {
pieChart = 'kolacovy',
width = 'sirka',
height = 'vyska',
stack = 'na sobe',
colors = 'barvy',
group = 'skupina',
xlegend = 'legenda x',
tooltip = 'tooltip',
accumulateTooltip = 'spojeny tooltip',
links = 'odkazy',
defcolor = 'default color',
scalePerGroup = 'oddelene stupnice',
unitsPrefix = 'jednotky pred',
unitsSuffix = 'jednotky za',
groupNames = 'nazvy skupin',
groupLegendsFloat = 'float legendy',
groupLegendsWidth = 'sirka legendy',
hideGroupLegends = 'skryt popis skupin',
slices = 'sektory',
slice = 'sektor',
radius = 'polomer',
percent = 'procenta',
float = 'float',
delimiter = 'oddelovac',
header = 'zahlavi',
footer = 'zapati',
left = 'vlevo',
right = 'vpravo',
} -- here is what you want to translate
local defColors = require "Modul:Diagram/DefaultColors"
local hideGroupLegends
local groupAlign = 'none'
local groupWidth
local function nulOrWhitespace( s )
return not s or mw.text.trim( s ) == ''
end
local function createGroupList( tab, legends, cols )
if #legends > 1 and not hideGroupLegends then
local divStyle
if groupAlign == 'left' then
divStyle = 'margin-right:8px;margin-top:10px;width:'..(groupWidth)..'px;float:left;'
elseif groupAlign == 'right' then
divStyle = 'margin-left:8px;margin-top:10px;width:'..(groupWidth)..'px;float:right;'
else
divStyle = ''
end
table.insert( tab, mw.text.tag( 'div', { style = divStyle } ) )
local list = {}
local spanStyle = "padding:0 1em;background-color:%s;box-shadow:2px -1px 4px 0 silver;margin-right:0.5em;"
for gi = 1, #legends do
local span = mw.text.tag( 'span', { style = string.format( spanStyle, cols[gi] ) }, ' ' ) .. ' '.. legends[gi]
table.insert( list, mw.text.tag( 'li', { style = "padding:0;"}, span ) )
end
table.insert( tab,
mw.text.tag( 'ul',
{style="width:100%;margin-left:8px;list-style:none;-webkit-column-width:12em;-moz-column-width:12em;column-width:12em;padding:0;"},
table.concat( list, '\n' )
)
)
table.insert( tab, '</div>' )
end
end
function pieChart( frame )
local res, imslices, args = {}, {}, frame.args
local radius
local values, colors, names, legends, links = {}, {}, {}, {}, {}
if args[keywords.groupLegendsFloat] == keywords.left then
groupAlign = 'left'
elseif args[keywords.groupLegendsFloat] == keywords.right then
groupAlign = 'right'
end
local delimiter = args[keywords.delimiter] or ':'
local lang = mw.getContentLanguage()
local float = args[keywords.float] or 'none'
local header = args[keywords.header]
local footer = args[keywords.footer]
function getArg( s, def, subst, with )
local result = args[keywords[s]] or def or ''
if subst and with then result = mw.ustring.gsub( result, subst, with ) end
return result
end
function analyzeParams()
function addSlice( i, slice )
local value, name, color, link = unpack( mw.text.split( slice, '%s*' .. delimiter .. '%s*' ) )
values[i] = tonumber( lang:parseFormattedNumber( value ) )
or error( string.format( 'Slice %d: "%s", first item("%s") could not be parsed as a number', i, value or '', sliceStr ) )
colors[i] = not nulOrWhitespace( color ) and color or defColors[i * 2]
names[i] = name or ''
links[i] = link
end
radius = getArg( 'radius', 150 )
hideGroupLegends = not nulOrWhitespace( args[keywords.hideGroupLegends] )
local slicesStr = getArg( 'slices' )
local prefix = getArg( 'unitsPrefix', '', '_', ' ' )
local suffix = getArg( 'unitsSuffix', '', '_', ' ' )
local percent = args[keywords.percent]
local sum = 0
local i, value = 0
for slice in mw.ustring.gmatch( slicesStr or '', "%b()" ) do
i = i + 1
addSlice( i, mw.ustring.match( slice, '^%(%s*(.-)%s*%)$' ) )
end
for k, v in pairs(args) do
local ind = mw.ustring.match( k, '^' .. keywords.slice .. '%s+(%d+)$' )
if ind then addSlice( tonumber( ind ), v ) end
end
for _, val in ipairs( values ) do sum = sum + val end
for i, value in ipairs( values ) do
local addprec = percent and string.format( ' (%0.1f %%)', value / sum * 100 ) or ''
legends[i] = mw.ustring.format( '%s: %s%s%s%s', names[i], prefix, lang:formatNum( value ), suffix, addprec )
links[i] = mw.text.trim( links[i] or mw.ustring.format( '[[#noSuchAnchor|%s]]', legends[i] ) )
end
end
function addRes( ... )
for _, v in pairs( { ... } ) do
table.insert( res, v )
end
end
function createImageMap()
addRes( '{{#tag:imagemap|', 'Image:Circle frame.svg{{!}}' .. ( radius * 2 ) .. 'px' )
addRes( unpack( imslices ) )
addRes( 'desc none', '}}' )
end
function drawSlice( i, q, start )
local color = colors[i]
local angle = ( .25 - start ) * 2 * math.pi
local sin, cos = math.abs( math.sin( angle ) ), math.abs( math.cos( angle ) )
local wsin, wcos = sin * radius, cos * radius
local s1, s2, w1, w2, w3, w4, width, border
local style
if q == 1 then
border = 'bottom'
w1, w2, w3, w4 = 0, 0, wsin, wcos
s1, s2 = 'bottom', 'left'
elseif q == 4 then
border = 'right'
w1, w2, w3, w4 = 0, wcos, wsin, 0
s1, s2 = 'bottom', 'right'
elseif q == 3 then
border = 'top'
w1, w2, w3, w4 = wsin, wcos, 0, 0
s1, s2 = 'top', 'right'
else
border = 'left'
w1, w2, w3, w4 = wsin, 0, 0, wcos
s1, s2 = 'top', 'left'
end
local style = string.format( 'position:absolute;%s:%spx;%s:%spx;width:%spx;height:%spx', s1, radius, s2, radius, radius, radius )
if start <= ( q - 1 ) * 0.25 then
style = string.format( '%s;border:0;background-color:%s', style, color )
else
style = string.format( '%s;border-width:%spx %spx %spx %spx;border-%s-color:%s', style, w1, w2, w3, w4, border, color )
end
addRes( mw.text.tag( 'div', { class = 'transborder', style = 'border: medium solid transparent; ' .. style }, '' ) )
end
function createSlices()
function coordsOfAngle( angle )
return ( 100 + math.floor( 100 * math.cos( angle ) ) ) .. ' ' .. ( 100 - math.floor( 100 * math.sin( angle ) ) )
end
local sum, start = 0, 0
for _, value in ipairs( values ) do sum = sum + value end
for i, value in ipairs(values) do
local poly = { 'poly 100 100' }
local startC, endC = start / sum, ( start + value ) / sum
local startQ, endQ = math.floor( startC * 4 + 1 ), math.floor( endC * 4 + 1 )
for q = startQ, math.min( endQ, 4 ) do drawSlice( i, q, startC ) end
for angle = ( .25 - startC ) * 2 * math.pi, ( .25 - endC ) * 2 * math.pi, -0.02 do
table.insert( poly, coordsOfAngle( angle ) )
end
table.insert( poly, coordsOfAngle( ( .25 - endC ) * 2 * math.pi ) .. ' 100 100 ' .. links[i] )
table.insert( imslices, table.concat( poly, ' ' ) )
start = start + values[i]
end
end
analyzeParams()
local width
groupWidth = args[keywords.groupLegendsWidth] or (radius * 2)
if groupAlign == 'none' then width = radius * 2 else width = (radius * 2 + groupWidth + 10) end
if #values == 0 then error( "no slices found - can't draw pie chart" ) end
addRes( mw.text.tag( 'div', { style = string.format( "max-width:%spx;float:%s;", width, float ) } ) )
if header then addRes( '<div style="font-weight:bold;text-align:center;vertical-align:middle;">' .. header .. '</div>' ) end
addRes( mw.text.tag( 'div', { style = string.format( 'position:relative;min-width:%spx;min-height:%spx;max-width:%spx;overflow:hidden;display:inline-block;', radius * 2, radius * 2, radius * 2 ) } ) )
createSlices()
addRes( mw.text.tag( 'div', { style = string.format( 'position:absolute;min-width:%spx;min-height:%spx;overflow:hidden;', radius * 2, radius * 2 ) } ) )
createImageMap()
addRes( '</div>' ) -- close "position:relative" div that contains slices and imagemap.
addRes( '</div>' ) -- close "position:relative" div that contains slices and imagemap.
createGroupList( res, legends, colors ) -- legends
addRes( '</div>') -- close containing div
if footer then addRes( '<div style="text-align:center">' .. footer .. '</div>' ) end
return frame:preprocess( table.concat( res, '\n' ) )
end
return {
[keywords.pieChart] = pieChart,
}
--</syntaxhighlight>